1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2017 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 <https://www.gnu.org/licenses/>. */
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #define DEFER_MS_W32_H
27 #include <mingw_time.h>
28 #include <stddef.h> /* for offsetof */
31 #include <float.h> /* for DBL_EPSILON */
38 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
40 #include <sys/utime.h>
43 /* Include (most) CRT headers *before* ms-w32.h. */
46 #include <string.h> /* for strerror, needed by sys_strerror */
47 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
73 char *sys_ctime (const time_t *);
74 int sys_chdir (const char *);
75 int sys_creat (const char *, int);
76 FILE *sys_fopen (const char *, const char *);
77 int sys_open (const char *, int, int);
78 int sys_rename (char const *, char const *);
79 int sys_rmdir (const char *);
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 *);
85 /* MinGW64 system headers include string.h too early, causing the
86 compiler to emit a warning about sys_strerror having no
88 char *sys_strerror (int);
91 extern void dynlib_reset_last_error (void);
95 #include "epaths.h" /* for PATH_EXEC */
101 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
102 use a different name to avoid compilation problems. */
103 typedef struct _MEMORY_STATUS_EX
{
106 DWORDLONG ullTotalPhys
;
107 DWORDLONG ullAvailPhys
;
108 DWORDLONG ullTotalPageFile
;
109 DWORDLONG ullAvailPageFile
;
110 DWORDLONG ullTotalVirtual
;
111 DWORDLONG ullAvailVirtual
;
112 DWORDLONG ullAvailExtendedVirtual
;
113 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
115 /* These are here so that GDB would know about these data types. This
116 allows attaching GDB to Emacs when a fatal exception is triggered
117 and Windows pops up the "application needs to be closed" dialog.
118 At that point, _gnu_exception_handler, the top-level exception
119 handler installed by the MinGW startup code, is somewhere on the
120 call-stack of the main thread, so going to that call frame and
121 looking at the argument to _gnu_exception_handler, which is a
122 PEXCEPTION_POINTERS pointer, can reveal the exception code
123 (excptr->ExceptionRecord->ExceptionCode) and the address where the
124 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
125 well as some additional information specific to the exception. */
126 PEXCEPTION_POINTERS excptr
;
127 PEXCEPTION_RECORD excprec
;
133 #include <tlhelp32.h>
138 #if _WIN32_WINNT < 0x0500
139 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
140 /* This either is not in psapi.h or guarded by higher value of
141 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
142 defines it in psapi.h */
143 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
145 DWORD PageFaultCount
;
146 SIZE_T PeakWorkingSetSize
;
147 SIZE_T WorkingSetSize
;
148 SIZE_T QuotaPeakPagedPoolUsage
;
149 SIZE_T QuotaPagedPoolUsage
;
150 SIZE_T QuotaPeakNonPagedPoolUsage
;
151 SIZE_T QuotaNonPagedPoolUsage
;
152 SIZE_T PagefileUsage
;
153 SIZE_T PeakPagefileUsage
;
155 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
159 #include <winioctl.h>
166 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
167 define them by hand if not already defined. */
168 #ifndef SDDL_REVISION_1
169 #define SDDL_REVISION_1 1
170 #endif /* SDDL_REVISION_1 */
172 #if defined(_MSC_VER) || defined(MINGW_W64)
173 /* MSVC and MinGW64 don't provide the definition of
174 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
175 which cannot be included because it triggers conflicts with other
176 Windows API headers. So we define it here by hand. */
178 typedef struct _REPARSE_DATA_BUFFER
{
180 USHORT ReparseDataLength
;
184 USHORT SubstituteNameOffset
;
185 USHORT SubstituteNameLength
;
186 USHORT PrintNameOffset
;
187 USHORT PrintNameLength
;
190 } SymbolicLinkReparseBuffer
;
192 USHORT SubstituteNameOffset
;
193 USHORT SubstituteNameLength
;
194 USHORT PrintNameOffset
;
195 USHORT PrintNameLength
;
197 } MountPointReparseBuffer
;
200 } GenericReparseBuffer
;
202 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
204 #ifndef FILE_DEVICE_FILE_SYSTEM
205 #define FILE_DEVICE_FILE_SYSTEM 9
207 #ifndef METHOD_BUFFERED
208 #define METHOD_BUFFERED 0
210 #ifndef FILE_ANY_ACCESS
211 #define FILE_ANY_ACCESS 0x00000000
214 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
216 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
217 #ifndef FSCTL_GET_REPARSE_POINT
218 #define FSCTL_GET_REPARSE_POINT \
219 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
223 /* TCP connection support. */
224 #include <sys/socket.h>
243 #include <iphlpapi.h> /* should be after winsock2.h */
245 #include <wincrypt.h>
247 #include <c-strcase.h>
248 #include <utimens.h> /* for fdutimens */
252 #include "w32common.h"
253 #include "w32select.h"
254 #include "systime.h" /* for current_timespec, struct timespec */
255 #include "dispextern.h" /* for xstrcasecmp */
256 #include "coding.h" /* for Vlocale_coding_system */
258 #include "careadlinkat.h"
259 #include "allocator.h"
261 /* For Lisp_Process, serial_configure and serial_open. */
265 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
266 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
268 static DWORD
get_rid (PSID
);
269 static int is_symlink (const char *);
270 static char * chase_symlinks (const char *);
271 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
272 static int restore_privilege (TOKEN_PRIVILEGES
*);
273 static BOOL WINAPI
revert_to_self (void);
275 static int sys_access (const char *, int);
276 extern void *e_malloc (size_t);
277 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
278 const struct timespec
*, const sigset_t
*);
279 extern int sys_dup (int);
282 /* Initialization states.
284 WARNING: If you add any more such variables for additional APIs,
285 you MUST add initialization for them to globals_of_w32
286 below. This is because these variables might get set
287 to non-NULL values during dumping, but the dumped Emacs
288 cannot reuse those values, because it could be run on a
289 different version of the OS, where API addresses are
291 static BOOL g_b_init_is_windows_9x
;
292 static BOOL g_b_init_open_process_token
;
293 static BOOL g_b_init_get_token_information
;
294 static BOOL g_b_init_lookup_account_sid
;
295 static BOOL g_b_init_get_sid_sub_authority
;
296 static BOOL g_b_init_get_sid_sub_authority_count
;
297 static BOOL g_b_init_get_security_info
;
298 static BOOL g_b_init_get_file_security_w
;
299 static BOOL g_b_init_get_file_security_a
;
300 static BOOL g_b_init_get_security_descriptor_owner
;
301 static BOOL g_b_init_get_security_descriptor_group
;
302 static BOOL g_b_init_is_valid_sid
;
303 static BOOL g_b_init_create_toolhelp32_snapshot
;
304 static BOOL g_b_init_process32_first
;
305 static BOOL g_b_init_process32_next
;
306 static BOOL g_b_init_open_thread_token
;
307 static BOOL g_b_init_impersonate_self
;
308 static BOOL g_b_init_revert_to_self
;
309 static BOOL g_b_init_get_process_memory_info
;
310 static BOOL g_b_init_get_process_working_set_size
;
311 static BOOL g_b_init_global_memory_status
;
312 static BOOL g_b_init_global_memory_status_ex
;
313 static BOOL g_b_init_get_length_sid
;
314 static BOOL g_b_init_equal_sid
;
315 static BOOL g_b_init_copy_sid
;
316 static BOOL g_b_init_get_native_system_info
;
317 static BOOL g_b_init_get_system_times
;
318 static BOOL g_b_init_create_symbolic_link_w
;
319 static BOOL g_b_init_create_symbolic_link_a
;
320 static BOOL g_b_init_get_security_descriptor_dacl
;
321 static BOOL g_b_init_convert_sd_to_sddl
;
322 static BOOL g_b_init_convert_sddl_to_sd
;
323 static BOOL g_b_init_is_valid_security_descriptor
;
324 static BOOL g_b_init_set_file_security_w
;
325 static BOOL g_b_init_set_file_security_a
;
326 static BOOL g_b_init_set_named_security_info_w
;
327 static BOOL g_b_init_set_named_security_info_a
;
328 static BOOL g_b_init_get_adapters_info
;
330 BOOL g_b_init_compare_string_w
;
331 BOOL g_b_init_debug_break_process
;
334 BEGIN: Wrapper functions around OpenProcessToken
335 and other functions in advapi32.dll that are only
336 supported in Windows NT / 2k / XP
338 /* ** Function pointer typedefs ** */
339 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
340 HANDLE ProcessHandle
,
342 PHANDLE TokenHandle
);
343 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
345 TOKEN_INFORMATION_CLASS TokenInformationClass
,
346 LPVOID TokenInformation
,
347 DWORD TokenInformationLength
,
348 PDWORD ReturnLength
);
349 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
350 HANDLE process_handle
,
351 LPFILETIME creation_time
,
352 LPFILETIME exit_time
,
353 LPFILETIME kernel_time
,
354 LPFILETIME user_time
);
356 GetProcessTimes_Proc get_process_times_fn
= NULL
;
359 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
361 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
363 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
364 LPCTSTR lpSystemName
,
369 LPDWORD cbDomainName
,
370 PSID_NAME_USE peUse
);
371 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
374 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
376 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
378 SE_OBJECT_TYPE ObjectType
,
379 SECURITY_INFORMATION SecurityInfo
,
384 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
385 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
387 SECURITY_INFORMATION RequestedInformation
,
388 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
390 LPDWORD lpnLengthNeeded
);
391 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
393 SECURITY_INFORMATION RequestedInformation
,
394 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
396 LPDWORD lpnLengthNeeded
);
397 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
399 SECURITY_INFORMATION SecurityInformation
,
400 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
401 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
403 SECURITY_INFORMATION SecurityInformation
,
404 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
405 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
406 LPCWSTR lpObjectName
,
407 SE_OBJECT_TYPE ObjectType
,
408 SECURITY_INFORMATION SecurityInformation
,
413 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
415 SE_OBJECT_TYPE ObjectType
,
416 SECURITY_INFORMATION SecurityInformation
,
421 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
422 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
424 LPBOOL lpbOwnerDefaulted
);
425 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
426 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
428 LPBOOL lpbGroupDefaulted
);
429 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
430 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
431 LPBOOL lpbDaclPresent
,
433 LPBOOL lpbDaclDefaulted
);
434 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
436 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
438 DWORD th32ProcessID
);
439 typedef BOOL (WINAPI
* Process32First_Proc
) (
441 LPPROCESSENTRY32 lppe
);
442 typedef BOOL (WINAPI
* Process32Next_Proc
) (
444 LPPROCESSENTRY32 lppe
);
445 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
449 PHANDLE TokenHandle
);
450 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
451 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
452 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
453 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
455 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
457 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
459 PSIZE_T lpMinimumWorkingSetSize
,
460 PSIZE_T lpMaximumWorkingSetSize
);
461 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
462 LPMEMORYSTATUS lpBuffer
);
463 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
464 LPMEMORY_STATUS_EX lpBuffer
);
465 typedef BOOL (WINAPI
* CopySid_Proc
) (
466 DWORD nDestinationSidLength
,
467 PSID pDestinationSid
,
469 typedef BOOL (WINAPI
* EqualSid_Proc
) (
472 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
474 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
475 LPSYSTEM_INFO lpSystemInfo
);
476 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
477 LPFILETIME lpIdleTime
,
478 LPFILETIME lpKernelTime
,
479 LPFILETIME lpUserTime
);
480 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
481 LPCWSTR lpSymlinkFileName
,
482 LPCWSTR lpTargetFileName
,
484 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
485 LPCSTR lpSymlinkFileName
,
486 LPCSTR lpTargetFileName
,
488 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
489 LPCTSTR StringSecurityDescriptor
,
490 DWORD StringSDRevision
,
491 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
492 PULONG SecurityDescriptorSize
);
493 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
494 PSECURITY_DESCRIPTOR SecurityDescriptor
,
495 DWORD RequestedStringSDRevision
,
496 SECURITY_INFORMATION SecurityInformation
,
497 LPTSTR
*StringSecurityDescriptor
,
498 PULONG StringSecurityDescriptorLen
);
499 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
500 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
501 PIP_ADAPTER_INFO pAdapterInfo
,
504 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
505 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
506 DWORD multiByteToWideCharFlags
;
508 /* ** A utility function ** */
512 static BOOL s_b_ret
= 0;
513 OSVERSIONINFO os_ver
;
514 if (g_b_init_is_windows_9x
== 0)
516 g_b_init_is_windows_9x
= 1;
517 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
518 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
519 if (GetVersionEx (&os_ver
))
521 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
527 static Lisp_Object
ltime (ULONGLONG
);
529 /* Get total user and system times for get-internal-run-time.
530 Returns a list of integers if the times are provided by the OS
531 (NT derivatives), otherwise it returns the result of current-time. */
532 Lisp_Object
w32_get_internal_run_time (void);
535 w32_get_internal_run_time (void)
537 if (get_process_times_fn
)
539 FILETIME create
, exit
, kernel
, user
;
540 HANDLE proc
= GetCurrentProcess ();
541 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
543 LARGE_INTEGER user_int
, kernel_int
, total
;
544 user_int
.LowPart
= user
.dwLowDateTime
;
545 user_int
.HighPart
= user
.dwHighDateTime
;
546 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
547 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
548 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
549 return ltime (total
.QuadPart
);
553 return Fcurrent_time ();
556 /* ** The wrapper functions ** */
559 open_process_token (HANDLE ProcessHandle
,
563 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
564 HMODULE hm_advapi32
= NULL
;
565 if (is_windows_9x () == TRUE
)
569 if (g_b_init_open_process_token
== 0)
571 g_b_init_open_process_token
= 1;
572 hm_advapi32
= LoadLibrary ("Advapi32.dll");
573 s_pfn_Open_Process_Token
=
574 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
576 if (s_pfn_Open_Process_Token
== NULL
)
581 s_pfn_Open_Process_Token (
589 get_token_information (HANDLE TokenHandle
,
590 TOKEN_INFORMATION_CLASS TokenInformationClass
,
591 LPVOID TokenInformation
,
592 DWORD TokenInformationLength
,
595 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
596 HMODULE hm_advapi32
= NULL
;
597 if (is_windows_9x () == TRUE
)
601 if (g_b_init_get_token_information
== 0)
603 g_b_init_get_token_information
= 1;
604 hm_advapi32
= LoadLibrary ("Advapi32.dll");
605 s_pfn_Get_Token_Information
=
606 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
608 if (s_pfn_Get_Token_Information
== NULL
)
613 s_pfn_Get_Token_Information (
615 TokenInformationClass
,
617 TokenInformationLength
,
623 lookup_account_sid (LPCTSTR lpSystemName
,
628 LPDWORD cbDomainName
,
631 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
632 HMODULE hm_advapi32
= NULL
;
633 if (is_windows_9x () == TRUE
)
637 if (g_b_init_lookup_account_sid
== 0)
639 g_b_init_lookup_account_sid
= 1;
640 hm_advapi32
= LoadLibrary ("Advapi32.dll");
641 s_pfn_Lookup_Account_Sid
=
642 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
644 if (s_pfn_Lookup_Account_Sid
== NULL
)
649 s_pfn_Lookup_Account_Sid (
661 get_sid_sub_authority (PSID pSid
, DWORD n
)
663 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
664 static DWORD zero
= 0U;
665 HMODULE hm_advapi32
= NULL
;
666 if (is_windows_9x () == TRUE
)
670 if (g_b_init_get_sid_sub_authority
== 0)
672 g_b_init_get_sid_sub_authority
= 1;
673 hm_advapi32
= LoadLibrary ("Advapi32.dll");
674 s_pfn_Get_Sid_Sub_Authority
=
675 (GetSidSubAuthority_Proc
) GetProcAddress (
676 hm_advapi32
, "GetSidSubAuthority");
678 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
682 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
686 get_sid_sub_authority_count (PSID pSid
)
688 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
689 static UCHAR zero
= 0U;
690 HMODULE hm_advapi32
= NULL
;
691 if (is_windows_9x () == TRUE
)
695 if (g_b_init_get_sid_sub_authority_count
== 0)
697 g_b_init_get_sid_sub_authority_count
= 1;
698 hm_advapi32
= LoadLibrary ("Advapi32.dll");
699 s_pfn_Get_Sid_Sub_Authority_Count
=
700 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
701 hm_advapi32
, "GetSidSubAuthorityCount");
703 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
707 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
711 get_security_info (HANDLE handle
,
712 SE_OBJECT_TYPE ObjectType
,
713 SECURITY_INFORMATION SecurityInfo
,
718 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
720 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
721 HMODULE hm_advapi32
= NULL
;
722 if (is_windows_9x () == TRUE
)
726 if (g_b_init_get_security_info
== 0)
728 g_b_init_get_security_info
= 1;
729 hm_advapi32
= LoadLibrary ("Advapi32.dll");
730 s_pfn_Get_Security_Info
=
731 (GetSecurityInfo_Proc
) GetProcAddress (
732 hm_advapi32
, "GetSecurityInfo");
734 if (s_pfn_Get_Security_Info
== NULL
)
738 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
739 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
740 ppSecurityDescriptor
));
744 get_file_security (const char *lpFileName
,
745 SECURITY_INFORMATION RequestedInformation
,
746 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
748 LPDWORD lpnLengthNeeded
)
750 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
751 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
752 HMODULE hm_advapi32
= NULL
;
753 if (is_windows_9x () == TRUE
)
758 if (w32_unicode_filenames
)
760 wchar_t filename_w
[MAX_PATH
];
762 if (g_b_init_get_file_security_w
== 0)
764 g_b_init_get_file_security_w
= 1;
765 hm_advapi32
= LoadLibrary ("Advapi32.dll");
766 s_pfn_Get_File_SecurityW
=
767 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
770 if (s_pfn_Get_File_SecurityW
== NULL
)
775 filename_to_utf16 (lpFileName
, filename_w
);
776 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
777 pSecurityDescriptor
, nLength
,
782 char filename_a
[MAX_PATH
];
784 if (g_b_init_get_file_security_a
== 0)
786 g_b_init_get_file_security_a
= 1;
787 hm_advapi32
= LoadLibrary ("Advapi32.dll");
788 s_pfn_Get_File_SecurityA
=
789 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
792 if (s_pfn_Get_File_SecurityA
== NULL
)
797 filename_to_ansi (lpFileName
, filename_a
);
798 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
799 pSecurityDescriptor
, nLength
,
805 set_file_security (const char *lpFileName
,
806 SECURITY_INFORMATION SecurityInformation
,
807 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
809 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
810 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
811 HMODULE hm_advapi32
= NULL
;
812 if (is_windows_9x () == TRUE
)
817 if (w32_unicode_filenames
)
819 wchar_t filename_w
[MAX_PATH
];
821 if (g_b_init_set_file_security_w
== 0)
823 g_b_init_set_file_security_w
= 1;
824 hm_advapi32
= LoadLibrary ("Advapi32.dll");
825 s_pfn_Set_File_SecurityW
=
826 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
829 if (s_pfn_Set_File_SecurityW
== NULL
)
834 filename_to_utf16 (lpFileName
, filename_w
);
835 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
836 pSecurityDescriptor
));
840 char filename_a
[MAX_PATH
];
842 if (g_b_init_set_file_security_a
== 0)
844 g_b_init_set_file_security_a
= 1;
845 hm_advapi32
= LoadLibrary ("Advapi32.dll");
846 s_pfn_Set_File_SecurityA
=
847 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
850 if (s_pfn_Set_File_SecurityA
== NULL
)
855 filename_to_ansi (lpFileName
, filename_a
);
856 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
857 pSecurityDescriptor
));
862 set_named_security_info (LPCTSTR lpObjectName
,
863 SE_OBJECT_TYPE ObjectType
,
864 SECURITY_INFORMATION SecurityInformation
,
870 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
871 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
872 HMODULE hm_advapi32
= NULL
;
873 if (is_windows_9x () == TRUE
)
878 if (w32_unicode_filenames
)
880 wchar_t filename_w
[MAX_PATH
];
882 if (g_b_init_set_named_security_info_w
== 0)
884 g_b_init_set_named_security_info_w
= 1;
885 hm_advapi32
= LoadLibrary ("Advapi32.dll");
886 s_pfn_Set_Named_Security_InfoW
=
887 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
888 "SetNamedSecurityInfoW");
890 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
895 filename_to_utf16 (lpObjectName
, filename_w
);
896 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
897 SecurityInformation
, psidOwner
,
898 psidGroup
, pDacl
, pSacl
));
902 char filename_a
[MAX_PATH
];
904 if (g_b_init_set_named_security_info_a
== 0)
906 g_b_init_set_named_security_info_a
= 1;
907 hm_advapi32
= LoadLibrary ("Advapi32.dll");
908 s_pfn_Set_Named_Security_InfoA
=
909 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
910 "SetNamedSecurityInfoA");
912 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
917 filename_to_ansi (lpObjectName
, filename_a
);
918 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
919 SecurityInformation
, psidOwner
,
920 psidGroup
, pDacl
, pSacl
));
925 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
927 LPBOOL lpbOwnerDefaulted
)
929 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
930 HMODULE hm_advapi32
= NULL
;
931 if (is_windows_9x () == TRUE
)
936 if (g_b_init_get_security_descriptor_owner
== 0)
938 g_b_init_get_security_descriptor_owner
= 1;
939 hm_advapi32
= LoadLibrary ("Advapi32.dll");
940 s_pfn_Get_Security_Descriptor_Owner
=
941 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
942 hm_advapi32
, "GetSecurityDescriptorOwner");
944 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
949 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
954 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
956 LPBOOL lpbGroupDefaulted
)
958 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
959 HMODULE hm_advapi32
= NULL
;
960 if (is_windows_9x () == TRUE
)
965 if (g_b_init_get_security_descriptor_group
== 0)
967 g_b_init_get_security_descriptor_group
= 1;
968 hm_advapi32
= LoadLibrary ("Advapi32.dll");
969 s_pfn_Get_Security_Descriptor_Group
=
970 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
971 hm_advapi32
, "GetSecurityDescriptorGroup");
973 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
978 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
983 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
984 LPBOOL lpbDaclPresent
,
986 LPBOOL lpbDaclDefaulted
)
988 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
989 HMODULE hm_advapi32
= NULL
;
990 if (is_windows_9x () == TRUE
)
995 if (g_b_init_get_security_descriptor_dacl
== 0)
997 g_b_init_get_security_descriptor_dacl
= 1;
998 hm_advapi32
= LoadLibrary ("Advapi32.dll");
999 s_pfn_Get_Security_Descriptor_Dacl
=
1000 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
1001 hm_advapi32
, "GetSecurityDescriptorDacl");
1003 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
1008 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
1009 lpbDaclPresent
, pDacl
,
1014 is_valid_sid (PSID sid
)
1016 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
1017 HMODULE hm_advapi32
= NULL
;
1018 if (is_windows_9x () == TRUE
)
1022 if (g_b_init_is_valid_sid
== 0)
1024 g_b_init_is_valid_sid
= 1;
1025 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1026 s_pfn_Is_Valid_Sid
=
1027 (IsValidSid_Proc
) GetProcAddress (
1028 hm_advapi32
, "IsValidSid");
1030 if (s_pfn_Is_Valid_Sid
== NULL
)
1034 return (s_pfn_Is_Valid_Sid (sid
));
1038 equal_sid (PSID sid1
, PSID sid2
)
1040 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1041 HMODULE hm_advapi32
= NULL
;
1042 if (is_windows_9x () == TRUE
)
1046 if (g_b_init_equal_sid
== 0)
1048 g_b_init_equal_sid
= 1;
1049 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1051 (EqualSid_Proc
) GetProcAddress (
1052 hm_advapi32
, "EqualSid");
1054 if (s_pfn_Equal_Sid
== NULL
)
1058 return (s_pfn_Equal_Sid (sid1
, sid2
));
1062 get_length_sid (PSID sid
)
1064 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1065 HMODULE hm_advapi32
= NULL
;
1066 if (is_windows_9x () == TRUE
)
1070 if (g_b_init_get_length_sid
== 0)
1072 g_b_init_get_length_sid
= 1;
1073 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1074 s_pfn_Get_Length_Sid
=
1075 (GetLengthSid_Proc
) GetProcAddress (
1076 hm_advapi32
, "GetLengthSid");
1078 if (s_pfn_Get_Length_Sid
== NULL
)
1082 return (s_pfn_Get_Length_Sid (sid
));
1086 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1088 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1089 HMODULE hm_advapi32
= NULL
;
1090 if (is_windows_9x () == TRUE
)
1094 if (g_b_init_copy_sid
== 0)
1096 g_b_init_copy_sid
= 1;
1097 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1099 (CopySid_Proc
) GetProcAddress (
1100 hm_advapi32
, "CopySid");
1102 if (s_pfn_Copy_Sid
== NULL
)
1106 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1110 END: Wrapper functions around OpenProcessToken
1111 and other functions in advapi32.dll that are only
1112 supported in Windows NT / 2k / XP
1116 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1118 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1119 if (is_windows_9x () != TRUE
)
1121 if (g_b_init_get_native_system_info
== 0)
1123 g_b_init_get_native_system_info
= 1;
1124 s_pfn_Get_Native_System_Info
=
1125 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1126 "GetNativeSystemInfo");
1128 if (s_pfn_Get_Native_System_Info
!= NULL
)
1129 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1132 lpSystemInfo
->dwNumberOfProcessors
= -1;
1136 get_system_times (LPFILETIME lpIdleTime
,
1137 LPFILETIME lpKernelTime
,
1138 LPFILETIME lpUserTime
)
1140 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1141 if (is_windows_9x () == TRUE
)
1145 if (g_b_init_get_system_times
== 0)
1147 g_b_init_get_system_times
= 1;
1148 s_pfn_Get_System_times
=
1149 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1152 if (s_pfn_Get_System_times
== NULL
)
1154 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1157 static BOOLEAN WINAPI
1158 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1159 LPCSTR lpTargetFileName
,
1162 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1163 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1166 if (is_windows_9x () == TRUE
)
1171 if (w32_unicode_filenames
)
1173 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1175 if (g_b_init_create_symbolic_link_w
== 0)
1177 g_b_init_create_symbolic_link_w
= 1;
1178 s_pfn_Create_Symbolic_LinkW
=
1179 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1180 "CreateSymbolicLinkW");
1182 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1188 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1189 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1190 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1191 /* If we were denied creation of the symlink, try again after
1192 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1195 TOKEN_PRIVILEGES priv_current
;
1197 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1200 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1201 restore_privilege (&priv_current
);
1208 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1210 if (g_b_init_create_symbolic_link_a
== 0)
1212 g_b_init_create_symbolic_link_a
= 1;
1213 s_pfn_Create_Symbolic_LinkA
=
1214 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1215 "CreateSymbolicLinkA");
1217 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1223 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1224 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1225 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1226 /* If we were denied creation of the symlink, try again after
1227 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1230 TOKEN_PRIVILEGES priv_current
;
1232 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1235 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1236 restore_privilege (&priv_current
);
1245 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1247 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1249 if (is_windows_9x () == TRUE
)
1255 if (g_b_init_is_valid_security_descriptor
== 0)
1257 g_b_init_is_valid_security_descriptor
= 1;
1258 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1259 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1260 "IsValidSecurityDescriptor");
1262 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1268 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1272 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1273 DWORD RequestedStringSDRevision
,
1274 SECURITY_INFORMATION SecurityInformation
,
1275 LPTSTR
*StringSecurityDescriptor
,
1276 PULONG StringSecurityDescriptorLen
)
1278 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1281 if (is_windows_9x () == TRUE
)
1287 if (g_b_init_convert_sd_to_sddl
== 0)
1289 g_b_init_convert_sd_to_sddl
= 1;
1291 s_pfn_Convert_SD_To_SDDL
=
1292 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1293 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1295 s_pfn_Convert_SD_To_SDDL
=
1296 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1297 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1300 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1306 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1307 RequestedStringSDRevision
,
1308 SecurityInformation
,
1309 StringSecurityDescriptor
,
1310 StringSecurityDescriptorLen
);
1316 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1317 DWORD StringSDRevision
,
1318 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1319 PULONG SecurityDescriptorSize
)
1321 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1324 if (is_windows_9x () == TRUE
)
1330 if (g_b_init_convert_sddl_to_sd
== 0)
1332 g_b_init_convert_sddl_to_sd
= 1;
1334 s_pfn_Convert_SDDL_To_SD
=
1335 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1336 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1338 s_pfn_Convert_SDDL_To_SD
=
1339 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1340 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1343 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1349 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1352 SecurityDescriptorSize
);
1358 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1360 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1361 HMODULE hm_iphlpapi
= NULL
;
1363 if (is_windows_9x () == TRUE
)
1364 return ERROR_NOT_SUPPORTED
;
1366 if (g_b_init_get_adapters_info
== 0)
1368 g_b_init_get_adapters_info
= 1;
1369 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1371 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1372 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1374 if (s_pfn_Get_Adapters_Info
== NULL
)
1375 return ERROR_NOT_SUPPORTED
;
1376 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1381 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1382 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1384 This is called from alloc.c:valid_pointer_p. */
1386 w32_valid_pointer_p (void *p
, int size
)
1389 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1393 unsigned char *buf
= alloca (size
);
1394 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1405 /* Here's an overview of how the Windows build supports file names
1406 that cannot be encoded by the current system codepage.
1408 From the POV of Lisp and layers of C code above the functions here,
1409 Emacs on Windows pretends that its file names are encoded in UTF-8;
1410 see encode_file and decode_file on coding.c. Any file name that is
1411 passed as a unibyte string to C functions defined here is assumed
1412 to be in UTF-8 encoding. Any file name returned by functions
1413 defined here must be in UTF-8 encoding, with only a few exceptions
1414 reserved for a couple of special cases. (Be sure to use
1415 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1416 as they can be much longer than MAX_PATH!)
1418 The UTF-8 encoded file names cannot be passed to system APIs, as
1419 Windows does not support that. Therefore, they are converted
1420 either to UTF-16 or to the ANSI codepage, depending on the value of
1421 w32-unicode-filenames, before calling any system APIs or CRT library
1422 functions. The default value of that variable is determined by the
1423 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1424 user can change that default (although I don't see why would she
1427 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1428 filename_from_utf16, and filename_from_ansi, are the workhorses of
1429 these conversions. They rely on Windows native APIs
1430 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1431 functions from coding.c here, because they allocate memory, which
1432 is a bad idea on the level of libc, which is what the functions
1433 here emulate. (If you worry about performance due to constant
1434 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1435 it was measured to take only a few microseconds on a not-so-fast
1436 machine, and second, that's exactly what the ANSI APIs we used
1437 before did anyway, because they are just thin wrappers around the
1440 The variables file-name-coding-system and default-file-name-coding-system
1441 still exist, but are actually used only when a file name needs to
1442 be converted to the ANSI codepage. This happens all the time when
1443 w32-unicode-filenames is nil, but can also happen from time to time
1444 when it is t. Otherwise, these variables have no effect on file-name
1445 encoding when w32-unicode-filenames is t; this is similar to
1446 selection-coding-system.
1448 This arrangement works very well, but it has a few gotchas and
1451 . Lisp code that encodes or decodes file names manually should
1452 normally use 'utf-8' as the coding-system on Windows,
1453 disregarding file-name-coding-system. This is a somewhat
1454 unpleasant consequence, but it cannot be avoided. Fortunately,
1455 very few Lisp packages need to do that.
1457 More generally, passing to library functions (e.g., fopen or
1458 opendir) file names already encoded in the ANSI codepage is
1459 explicitly *verboten*, as all those functions, as shadowed and
1460 emulated here, assume they will receive UTF-8 encoded file names.
1462 For the same reasons, no CRT function or Win32 API can be called
1463 directly in Emacs sources, without either converting the file
1464 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1465 some shadowing function defined here.
1467 . Environment variables stored in Vprocess_environment are encoded
1468 in the ANSI codepage, so if getenv/egetenv is used for a variable
1469 whose value is a file name or a list of directories, it needs to
1470 be converted to UTF-8, before it is used as argument to functions
1471 or decoded into a Lisp string.
1473 . File names passed to external libraries, like the image libraries
1474 and GnuTLS, need special handling. These libraries generally
1475 don't support UTF-16 or UTF-8 file names, so they must get file
1476 names encoded in the ANSI codepage. To facilitate using these
1477 libraries with file names that are not encodable in the ANSI
1478 codepage, use the function ansi_encode_filename, which will try
1479 to use the short 8+3 alias of a file name if that file name is
1480 not encodable in the ANSI codepage. See image.c and gnutls.c for
1481 examples of how this should be done.
1483 . Running subprocesses in non-ASCII directories and with non-ASCII
1484 file arguments is limited to the current codepage (even though
1485 Emacs is perfectly capable of finding an executable program file
1486 in a directory whose name cannot be encoded in the current
1487 codepage). This is because the command-line arguments are
1488 encoded _before_ they get to the w32-specific level, and the
1489 encoding is not known in advance (it doesn't have to be the
1490 current ANSI codepage), so w32proc.c functions cannot re-encode
1491 them in UTF-16. This should be fixed, but will also require
1492 changes in cmdproxy. The current limitation is not terribly bad
1493 anyway, since very few, if any, Windows console programs that are
1494 likely to be invoked by Emacs support UTF-16 encoded command
1497 . For similar reasons, server.el and emacsclient are also limited
1498 to the current ANSI codepage for now.
1500 . Emacs itself can only handle command-line arguments encoded in
1501 the current codepage.
1503 . Turning on w32-unicode-filename on Windows 9X (if it at all
1504 works) requires UNICOWS.DLL, which is thus a requirement even in
1505 non-GUI sessions, something that we previously avoided. */
1509 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1510 codepage defined by file-name-coding-system. */
1512 /* Current codepage for encoding file names. */
1513 static int file_name_codepage
;
1515 /* Initialize the codepage used for decoding file names. This is
1516 needed to undo the value recorded during dumping, which might not
1517 be correct when we run the dumped Emacs. */
1519 w32_init_file_name_codepage (void)
1521 file_name_codepage
= CP_ACP
;
1522 w32_ansi_code_page
= CP_ACP
;
1525 /* Produce a Windows ANSI codepage suitable for encoding file names.
1526 Return the information about that codepage in CP_INFO. */
1528 codepage_for_filenames (CPINFO
*cp_info
)
1530 /* A simple cache to avoid calling GetCPInfo every time we need to
1531 encode/decode a file name. The file-name encoding is not
1532 supposed to be changed too frequently, if ever. */
1533 static Lisp_Object last_file_name_encoding
;
1535 Lisp_Object current_encoding
;
1537 current_encoding
= Vfile_name_coding_system
;
1538 if (NILP (current_encoding
))
1539 current_encoding
= Vdefault_file_name_coding_system
;
1541 if (!EQ (last_file_name_encoding
, current_encoding
)
1542 || NILP (last_file_name_encoding
))
1544 /* Default to the current ANSI codepage. */
1545 file_name_codepage
= w32_ansi_code_page
;
1547 if (!NILP (current_encoding
))
1549 char *cpname
= SSDATA (SYMBOL_NAME (current_encoding
));
1550 char *cp
= NULL
, *end
;
1553 if (strncmp (cpname
, "cp", 2) == 0)
1555 else if (strncmp (cpname
, "windows-", 8) == 0)
1561 cpnum
= strtol (cp
, &end
, 10);
1562 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1563 file_name_codepage
= cpnum
;
1567 if (!file_name_codepage
)
1568 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1570 if (!GetCPInfo (file_name_codepage
, &cp
))
1572 file_name_codepage
= CP_ACP
;
1573 if (!GetCPInfo (file_name_codepage
, &cp
))
1577 /* Cache the new value. */
1578 last_file_name_encoding
= current_encoding
;
1583 return file_name_codepage
;
1587 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1589 int result
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, fn_in
,
1590 -1, fn_out
, MAX_PATH
);
1594 DWORD err
= GetLastError ();
1598 case ERROR_INVALID_FLAGS
:
1599 case ERROR_INVALID_PARAMETER
:
1602 case ERROR_INSUFFICIENT_BUFFER
:
1603 case ERROR_NO_UNICODE_TRANSLATION
:
1614 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1616 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1617 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1621 DWORD err
= GetLastError ();
1625 case ERROR_INVALID_FLAGS
:
1626 case ERROR_INVALID_PARAMETER
:
1629 case ERROR_INSUFFICIENT_BUFFER
:
1630 case ERROR_NO_UNICODE_TRANSLATION
:
1641 filename_to_ansi (const char *fn_in
, char *fn_out
)
1643 wchar_t fn_utf16
[MAX_PATH
];
1645 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1648 int codepage
= codepage_for_filenames (NULL
);
1650 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1651 fn_out
, MAX_PATH
, NULL
, NULL
);
1654 DWORD err
= GetLastError ();
1658 case ERROR_INVALID_FLAGS
:
1659 case ERROR_INVALID_PARAMETER
:
1662 case ERROR_INSUFFICIENT_BUFFER
:
1663 case ERROR_NO_UNICODE_TRANSLATION
:
1676 filename_from_ansi (const char *fn_in
, char *fn_out
)
1678 wchar_t fn_utf16
[MAX_PATH
];
1679 int codepage
= codepage_for_filenames (NULL
);
1680 int result
= pMultiByteToWideChar (codepage
, multiByteToWideCharFlags
, fn_in
,
1681 -1, fn_utf16
, MAX_PATH
);
1685 DWORD err
= GetLastError ();
1689 case ERROR_INVALID_FLAGS
:
1690 case ERROR_INVALID_PARAMETER
:
1693 case ERROR_INSUFFICIENT_BUFFER
:
1694 case ERROR_NO_UNICODE_TRANSLATION
:
1701 return filename_from_utf16 (fn_utf16
, fn_out
);
1706 /* The directory where we started, in UTF-8. */
1707 static char startup_dir
[MAX_UTF8_PATH
];
1709 /* Get the current working directory. */
1711 getcwd (char *dir
, int dirsize
)
1718 if (dirsize
<= strlen (startup_dir
))
1724 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1728 /* Emacs doesn't actually change directory itself, it stays in the
1729 same directory where it was started. */
1730 strcpy (dir
, startup_dir
);
1735 /* Emulate getloadavg. */
1737 struct load_sample
{
1744 /* Number of processors on this machine. */
1745 static unsigned num_of_processors
;
1747 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1748 static struct load_sample samples
[16*60];
1749 static int first_idx
= -1, last_idx
= -1;
1750 static int max_idx
= ARRAYELTS (samples
);
1755 int next_idx
= from
+ 1;
1757 if (next_idx
>= max_idx
)
1766 int prev_idx
= from
- 1;
1769 prev_idx
= max_idx
- 1;
1775 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1777 SYSTEM_INFO sysinfo
;
1778 FILETIME ft_idle
, ft_user
, ft_kernel
;
1780 /* Initialize the number of processors on this machine. */
1781 if (num_of_processors
<= 0)
1783 get_native_system_info (&sysinfo
);
1784 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1785 if (num_of_processors
<= 0)
1787 GetSystemInfo (&sysinfo
);
1788 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1790 if (num_of_processors
<= 0)
1791 num_of_processors
= 1;
1794 /* TODO: Take into account threads that are ready to run, by
1795 sampling the "\System\Processor Queue Length" performance
1796 counter. The code below accounts only for threads that are
1797 actually running. */
1799 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1801 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1803 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1804 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1805 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1806 *idle
= uidle
.QuadPart
;
1807 *kernel
= ukernel
.QuadPart
;
1808 *user
= uuser
.QuadPart
;
1818 /* Produce the load average for a given time interval, using the
1819 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1820 1-minute, 5-minute, or 15-minute average, respectively. */
1824 double retval
= -1.0;
1827 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1828 time_t now
= samples
[last_idx
].sample_time
;
1830 if (first_idx
!= last_idx
)
1832 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1834 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1835 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1838 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1839 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1840 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1842 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1845 if (idx
== first_idx
)
1854 getloadavg (double loadavg
[], int nelem
)
1857 ULONGLONG idle
, kernel
, user
;
1858 time_t now
= time (NULL
);
1860 /* If system time jumped back for some reason, delete all samples
1861 whose time is later than the current wall-clock time. This
1862 prevents load average figures from becoming frozen for prolonged
1863 periods of time, when system time is reset backwards. */
1866 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1868 if (last_idx
== first_idx
)
1870 first_idx
= last_idx
= -1;
1873 last_idx
= buf_prev (last_idx
);
1877 /* Store another sample. We ignore samples that are less than 1 sec
1880 || (difftime (now
, samples
[last_idx
].sample_time
)
1881 >= 1.0 - 2*DBL_EPSILON
*now
))
1883 sample_system_load (&idle
, &kernel
, &user
);
1884 last_idx
= buf_next (last_idx
);
1885 samples
[last_idx
].sample_time
= now
;
1886 samples
[last_idx
].idle
= idle
;
1887 samples
[last_idx
].kernel
= kernel
;
1888 samples
[last_idx
].user
= user
;
1889 /* If the buffer has more that 15 min worth of samples, discard
1891 if (first_idx
== -1)
1892 first_idx
= last_idx
;
1893 while (first_idx
!= last_idx
1894 && (difftime (now
, samples
[first_idx
].sample_time
)
1895 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1896 first_idx
= buf_next (first_idx
);
1899 for (elem
= 0; elem
< nelem
; elem
++)
1901 double avg
= getavg (elem
);
1905 loadavg
[elem
] = avg
;
1911 /* Emulate getpwuid, getpwnam and others. */
1913 #define PASSWD_FIELD_SIZE 256
1915 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1916 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1917 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1918 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1919 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1921 static struct passwd dflt_passwd
=
1933 static char dflt_group_name
[GNLEN
+1];
1935 static struct group dflt_group
=
1937 /* When group information is not available, we return this as the
1938 group for all files. */
1946 return dflt_passwd
.pw_uid
;
1952 /* I could imagine arguing for checking to see whether the user is
1953 in the Administrators group and returning a UID of 0 for that
1954 case, but I don't know how wise that would be in the long run. */
1961 return dflt_passwd
.pw_gid
;
1971 getpwuid (unsigned uid
)
1973 if (uid
== dflt_passwd
.pw_uid
)
1974 return &dflt_passwd
;
1979 getgrgid (gid_t gid
)
1985 getpwnam (char *name
)
1989 pw
= getpwuid (getuid ());
1993 if (xstrcasecmp (name
, pw
->pw_name
))
2000 init_user_info (void)
2002 /* Find the user's real name by opening the process token and
2003 looking up the name associated with the user-sid in that token.
2005 Use the relative portion of the identifier authority value from
2006 the user-sid as the user id value (same for group id using the
2007 primary group sid from the process token). */
2009 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
2010 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
2011 DWORD glength
= sizeof (gname
);
2012 HANDLE token
= NULL
;
2013 SID_NAME_USE user_type
;
2014 unsigned char *buf
= NULL
;
2016 TOKEN_USER user_token
;
2017 TOKEN_PRIMARY_GROUP group_token
;
2020 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
2023 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
2024 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2026 buf
= xmalloc (blen
);
2027 result
= get_token_information (token
, TokenUser
,
2028 (LPVOID
)buf
, blen
, &needed
);
2031 memcpy (&user_token
, buf
, sizeof (user_token
));
2032 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
2034 domain
, &dlength
, &user_type
);
2042 strcpy (dflt_passwd
.pw_name
, uname
);
2043 /* Determine a reasonable uid value. */
2044 if (xstrcasecmp ("administrator", uname
) == 0)
2046 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2047 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2051 /* Use the last sub-authority value of the RID, the relative
2052 portion of the SID, as user/group ID. */
2053 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2055 /* Get group id and name. */
2056 result
= get_token_information (token
, TokenPrimaryGroup
,
2057 (LPVOID
)buf
, blen
, &needed
);
2058 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2060 buf
= xrealloc (buf
, blen
= needed
);
2061 result
= get_token_information (token
, TokenPrimaryGroup
,
2062 (LPVOID
)buf
, blen
, &needed
);
2066 memcpy (&group_token
, buf
, sizeof (group_token
));
2067 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2068 dlength
= sizeof (domain
);
2069 /* If we can get at the real Primary Group name, use that.
2070 Otherwise, the default group name was already set to
2071 "None" in globals_of_w32. */
2072 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2073 gname
, &glength
, NULL
, &dlength
,
2075 strcpy (dflt_group_name
, gname
);
2078 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2081 /* If security calls are not supported (presumably because we
2082 are running under Windows 9X), fallback to this: */
2083 else if (GetUserName (uname
, &ulength
))
2085 strcpy (dflt_passwd
.pw_name
, uname
);
2086 if (xstrcasecmp ("administrator", uname
) == 0)
2087 dflt_passwd
.pw_uid
= 0;
2089 dflt_passwd
.pw_uid
= 123;
2090 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2094 strcpy (dflt_passwd
.pw_name
, "unknown");
2095 dflt_passwd
.pw_uid
= 123;
2096 dflt_passwd
.pw_gid
= 123;
2098 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2100 /* Set dir and shell from environment variables. */
2101 if (w32_unicode_filenames
)
2103 wchar_t *home
= _wgetenv (L
"HOME");
2104 wchar_t *shell
= _wgetenv (L
"SHELL");
2106 /* Ensure HOME and SHELL are defined. */
2111 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2112 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2116 char *home
= getenv ("HOME");
2117 char *shell
= getenv ("SHELL");
2123 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2124 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2129 CloseHandle (token
);
2132 static HCRYPTPROV w32_crypto_hprov
;
2134 w32_init_crypt_random (void)
2136 if (!CryptAcquireContext (&w32_crypto_hprov
, NULL
, NULL
, PROV_RSA_FULL
,
2137 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
2139 DebPrint (("CryptAcquireContext failed with error %x\n",
2141 w32_crypto_hprov
= 0;
2148 w32_init_random (void *buf
, ptrdiff_t buflen
)
2150 if (!w32_crypto_hprov
)
2151 w32_init_crypt_random ();
2152 if (w32_crypto_hprov
)
2154 if (CryptGenRandom (w32_crypto_hprov
, buflen
, (BYTE
*)buf
))
2160 /* MS-Windows 'rand' produces separate identical series for each
2161 thread, so we replace it with our version. */
2163 /* Algorithm AS183: An Efficient and Portable Pseudo-random Number
2164 Generator, by B.A. Wichmann, I.D. Hill. AS, v31, No. 2 (1982). */
2165 static int ix
= 3172, iy
= 9814, iz
= 20125;
2166 #define RAND_MAX_X 30269
2167 #define RAND_MAX_Y 30307
2168 #define RAND_MAX_Z 30323
2173 ix
= (171 * ix
) % RAND_MAX_X
;
2174 iy
= (172 * iy
) % RAND_MAX_Y
;
2175 iz
= (170 * iz
) % RAND_MAX_Z
;
2177 return (ix
+ iy
+ iz
) & 0x7fff;
2183 /* rand_as183 () gives us 15 random bits...hack together 30 bits. */
2184 return ((rand_as183 () << 15) | rand_as183 ());
2191 ix
= rand () % RAND_MAX_X
;
2192 iy
= rand () % RAND_MAX_Y
;
2193 iz
= rand () % RAND_MAX_Z
;
2196 /* Return the maximum length in bytes of a multibyte character
2197 sequence encoded in the current ANSI codepage. This is required to
2198 correctly walk the encoded file names one character at a time. */
2200 max_filename_mbslen (void)
2204 codepage_for_filenames (&cp_info
);
2205 return cp_info
.MaxCharSize
;
2208 /* Normalize filename by converting in-place all of its path
2209 separators to the separator specified by PATH_SEP. */
2212 normalize_filename (register char *fp
, char path_sep
)
2216 /* Always lower-case drive letters a-z, even if the filesystem
2217 preserves case in filenames.
2218 This is so filenames can be compared by string comparison
2219 functions that are case-sensitive. Even case-preserving filesystems
2220 do not distinguish case in drive letters. */
2223 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2231 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2237 /* Destructively turn backslashes into slashes. */
2239 dostounix_filename (register char *p
)
2241 normalize_filename (p
, '/');
2244 /* Destructively turn slashes into backslashes. */
2246 unixtodos_filename (register char *p
)
2248 normalize_filename (p
, '\\');
2251 /* Remove all CR's that are followed by a LF.
2252 (From msdos.c...probably should figure out a way to share it,
2253 although this code isn't going to ever change.) */
2255 crlf_to_lf (register int n
, register char *buf
)
2257 unsigned char *np
= (unsigned char *)buf
;
2258 unsigned char *startp
= np
;
2259 char *endp
= buf
+ n
;
2263 while (buf
< endp
- 1)
2267 if (*(++buf
) != 0x0a)
2278 /* Parse the root part of file name, if present. Return length and
2279 optionally store pointer to char after root. */
2281 parse_root (const char * name
, const char ** pPath
)
2283 const char * start
= name
;
2288 /* find the root name of the volume if given */
2289 if (isalpha (name
[0]) && name
[1] == ':')
2291 /* skip past drive specifier */
2293 if (IS_DIRECTORY_SEP (name
[0]))
2296 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2303 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2308 if (IS_DIRECTORY_SEP (name
[0]))
2315 return name
- start
;
2318 /* Get long base name for name; name is assumed to be absolute. */
2320 get_long_basename (char * name
, char * buf
, int size
)
2322 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2323 char fname_utf8
[MAX_UTF8_PATH
];
2327 /* Must be valid filename, no wild cards or other invalid characters. */
2328 if (strpbrk (name
, "*?|<>\""))
2331 if (w32_unicode_filenames
)
2333 wchar_t fname_utf16
[MAX_PATH
];
2334 WIN32_FIND_DATAW find_data_wide
;
2336 filename_to_utf16 (name
, fname_utf16
);
2337 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2338 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2339 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2343 char fname_ansi
[MAX_PATH
];
2344 WIN32_FIND_DATAA find_data_ansi
;
2346 filename_to_ansi (name
, fname_ansi
);
2347 /* If the ANSI name includes ? characters, it is not encodable
2348 in the ANSI codepage. In that case, we deliver the question
2349 marks to the caller; calling FindFirstFileA in this case
2350 could return some unrelated file name in the same
2352 if (_mbspbrk (fname_ansi
, "?"))
2354 /* Find the basename of fname_ansi. */
2355 char *p
= strrchr (fname_ansi
, '\\');
2361 cstatus
= filename_from_ansi (p
, fname_utf8
);
2365 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2366 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2367 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2371 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2372 memcpy (buf
, fname_utf8
, len
+ 1);
2376 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2377 FindClose (dir_handle
);
2382 /* Get long name for file, if possible (assumed to be absolute). */
2384 w32_get_long_filename (const char * name
, char * buf
, int size
)
2389 char full
[ MAX_UTF8_PATH
];
2392 len
= strlen (name
);
2393 if (len
>= MAX_UTF8_PATH
)
2396 /* Use local copy for destructive modification. */
2397 memcpy (full
, name
, len
+1);
2398 unixtodos_filename (full
);
2400 /* Copy root part verbatim. */
2401 len
= parse_root (full
, (const char **)&p
);
2402 memcpy (o
, full
, len
);
2407 while (p
!= NULL
&& *p
)
2410 p
= strchr (q
, '\\');
2412 len
= get_long_basename (full
, o
, size
);
2435 w32_get_short_filename (const char * name
, char * buf
, int size
)
2437 if (w32_unicode_filenames
)
2439 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2440 unsigned int retval
;
2442 filename_to_utf16 (name
, name_utf16
);
2443 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2444 if (retval
&& retval
< size
)
2445 filename_from_utf16 (short_name
, buf
);
2450 char name_ansi
[MAX_PATH
];
2452 filename_to_ansi (name
, name_ansi
);
2453 return GetShortPathNameA (name_ansi
, buf
, size
);
2457 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2458 MS-Windows ANSI codepage. If FILENAME includes characters not
2459 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2460 if it exists. This is needed because the w32 build wants to
2461 support file names outside of the system locale, but image
2462 libraries typically don't support wide (a.k.a. "Unicode") APIs
2463 required for that. */
2466 ansi_encode_filename (Lisp_Object filename
)
2468 Lisp_Object encoded_filename
;
2469 char fname
[MAX_PATH
];
2471 filename_to_ansi (SSDATA (filename
), fname
);
2472 if (_mbspbrk (fname
, "?"))
2474 char shortname
[MAX_PATH
];
2476 if (w32_get_short_filename (SSDATA (filename
), shortname
, MAX_PATH
))
2478 dostounix_filename (shortname
);
2479 encoded_filename
= build_string (shortname
);
2482 encoded_filename
= build_unibyte_string (fname
);
2485 encoded_filename
= build_unibyte_string (fname
);
2486 return encoded_filename
;
2490 is_unc_volume (const char *filename
)
2492 const char *ptr
= filename
;
2494 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2497 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2503 /* Emulate the Posix unsetenv. */
2505 unsetenv (const char *name
)
2510 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2515 name_len
= strlen (name
);
2516 /* MS docs says an environment variable cannot be longer than 32K. */
2517 if (name_len
> 32767)
2522 /* It is safe to use 'alloca' with 32K size, since the stack is at
2523 least 2MB, and we set it to 8MB in the link command line. */
2524 var
= alloca (name_len
+ 2);
2525 strncpy (var
, name
, name_len
);
2526 var
[name_len
++] = '=';
2527 var
[name_len
] = '\0';
2528 return _putenv (var
);
2531 /* MS _putenv doesn't support removing a variable when the argument
2532 does not include the '=' character, so we fix that here. */
2534 sys_putenv (char *str
)
2536 const char *const name_end
= strchr (str
, '=');
2538 if (name_end
== NULL
)
2540 /* Remove the variable from the environment. */
2541 return unsetenv (str
);
2544 if (strncmp (str
, "TZ=<", 4) == 0)
2546 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2547 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2548 and to the undocumented placeholder "ZZZ" otherwise. */
2549 bool supported_abbr
= true;
2550 for (char *p
= str
+ 4; *p
; p
++)
2552 if (('0' <= *p
&& *p
<= '9') || *p
== '-' || *p
== '+')
2553 supported_abbr
= false;
2559 abbrlen
= p
- (str
+ 4);
2560 memmove (str
+ 3, str
+ 4, abbrlen
);
2565 memset (str
+ 3, 'Z', abbrlen
);
2567 memmove (str
+ 3 + abbrlen
, p
+ 1, strlen (p
));
2573 return _putenv (str
);
2576 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2579 w32_get_resource (const char *key
, LPDWORD lpdwtype
)
2582 HKEY hrootkey
= NULL
;
2585 /* Check both the current user and the local machine to see if
2586 we have any resources. */
2588 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2592 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2593 && (lpvalue
= xmalloc (cbData
)) != NULL
2594 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2596 RegCloseKey (hrootkey
);
2602 RegCloseKey (hrootkey
);
2605 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2609 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2610 && (lpvalue
= xmalloc (cbData
)) != NULL
2611 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2613 RegCloseKey (hrootkey
);
2619 RegCloseKey (hrootkey
);
2625 /* The argv[] array holds ANSI-encoded strings, and so this function
2626 works with ANS_encoded strings. */
2628 init_environment (char ** argv
)
2630 static const char * const tempdirs
[] = {
2631 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2636 const int imax
= ARRAYELTS (tempdirs
);
2638 /* Implementation note: This function explicitly works with ANSI
2639 file names, not with UTF-8 encoded file names. This is because
2640 this function pushes variables into the Emacs's environment, and
2641 the environment variables are always assumed to be in the
2642 locale-specific encoding. Do NOT call any functions that accept
2643 UTF-8 file names from this function! */
2645 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2646 temporary files and assume "/tmp" if $TMPDIR is unset, which
2647 will break on DOS/Windows. Refuse to work if we cannot find
2648 a directory, not even "c:/", usable for that purpose. */
2649 for (i
= 0; i
< imax
; i
++)
2651 const char *tmp
= tempdirs
[i
];
2654 tmp
= getenv (tmp
+ 1);
2655 /* Note that `access' can lie to us if the directory resides on a
2656 read-only filesystem, like CD-ROM or a write-protected floppy.
2657 The only way to be really sure is to actually create a file and
2658 see if it succeeds. But I think that's too much to ask. */
2660 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2661 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2663 char * var
= alloca (strlen (tmp
) + 8);
2664 sprintf (var
, "TMPDIR=%s", tmp
);
2665 _putenv (strdup (var
));
2672 Fcons (build_string ("no usable temporary directories found!!"),
2674 "While setting TMPDIR: ");
2676 /* Check for environment variables and use registry settings if they
2677 don't exist. Fallback on default values where applicable. */
2682 char locale_name
[32];
2683 char default_home
[MAX_PATH
];
2686 static const struct env_entry
2689 const char * def_value
;
2692 /* If the default value is NULL, we will use the value from the
2693 outside environment or the Registry, but will not push the
2694 variable into the Emacs environment if it is defined neither
2695 in the Registry nor in the outside environment. */
2697 {"PRELOAD_WINSOCK", NULL
},
2698 {"emacs_dir", "C:/emacs"},
2699 {"EMACSLOADPATH", NULL
},
2700 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2701 {"EMACSDATA", NULL
},
2702 {"EMACSPATH", NULL
},
2709 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2711 /* We need to copy dflt_envvars[] and work on the copy because we
2712 don't want the dumped Emacs to inherit the values of
2713 environment variables we saw during dumping (which could be on
2714 a different system). The defaults above must be left intact. */
2715 struct env_entry env_vars
[N_ENV_VARS
];
2717 for (i
= 0; i
< N_ENV_VARS
; i
++)
2718 env_vars
[i
] = dflt_envvars
[i
];
2720 /* For backwards compatibility, check if a .emacs file exists in C:/
2721 If not, then we can try to default to the appdata directory under the
2722 user's profile, which is more likely to be writable. */
2723 if (sys_access ("C:/.emacs", F_OK
) != 0)
2725 HRESULT profile_result
;
2726 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2727 of Windows 95 and NT4 that have not been updated to include
2729 ShGetFolderPath_fn get_folder_path
;
2730 get_folder_path
= (ShGetFolderPath_fn
)
2731 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2733 if (get_folder_path
!= NULL
)
2735 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2738 /* If we can't get the appdata dir, revert to old behavior. */
2739 if (profile_result
== S_OK
)
2741 env_vars
[0].def_value
= default_home
;
2747 /* Get default locale info and use it for LANG. */
2748 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2749 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2750 locale_name
, sizeof (locale_name
)))
2752 for (i
= 0; i
< N_ENV_VARS
; i
++)
2754 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2756 env_vars
[i
].def_value
= locale_name
;
2762 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2764 /* Treat emacs_dir specially: set it unconditionally based on our
2768 char modname
[MAX_PATH
];
2770 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2772 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2776 if ((p
= _mbsrchr (modname
, '\\'))
2777 /* From bin means installed Emacs, from src means uninstalled. */
2778 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2780 char buf
[SET_ENV_BUF_SIZE
];
2781 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2784 for (p
= modname
; *p
; p
= CharNext (p
))
2785 if (*p
== '\\') *p
= '/';
2787 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2788 _putenv (strdup (buf
));
2789 /* If we are running from the Posix-like build tree, define
2790 SHELL to point to our own cmdproxy. The loop below will
2791 then disregard PATH_EXEC and the default value. */
2792 if (within_build_tree
)
2794 _snprintf (buf
, sizeof (buf
) - 1,
2795 "SHELL=%s/nt/cmdproxy.exe", modname
);
2796 _putenv (strdup (buf
));
2801 for (i
= 0; i
< N_ENV_VARS
; i
++)
2803 if (!getenv (env_vars
[i
].name
))
2806 char bufc
[SET_ENV_BUF_SIZE
];
2808 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2809 /* Also ignore empty environment variables. */
2814 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2816 /* Look for cmdproxy.exe in every directory in
2817 PATH_EXEC. FIXME: This does not find cmdproxy
2818 in nt/ when we run uninstalled. */
2819 char fname
[MAX_PATH
];
2820 const char *pstart
= PATH_EXEC
, *pend
;
2823 pend
= _mbschr (pstart
, ';');
2825 pend
= pstart
+ strlen (pstart
);
2826 /* Be defensive against series of ;;; characters. */
2829 strncpy (fname
, pstart
, pend
- pstart
);
2830 fname
[pend
- pstart
] = '/';
2831 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2832 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2834 if (sys_access (bufc
, F_OK
) == 0)
2847 /* If not found in any directory, use the
2848 default as the last resort. */
2849 lpval
= (char *)env_vars
[i
].def_value
;
2850 dwType
= REG_EXPAND_SZ
;
2856 lpval
= (char *)env_vars
[i
].def_value
;
2857 dwType
= REG_EXPAND_SZ
;
2859 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2860 Vdelayed_warnings_list
2862 (listn (CONSTYPE_HEAP
, 2,
2863 intern ("initialization"), build_string
2864 ("Use of `C:\\.emacs' without defining `HOME'\n"
2865 "in the environment is deprecated, "
2866 "see `Windows HOME' in the Emacs manual.")),
2867 Vdelayed_warnings_list
);
2872 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2874 if (dwType
== REG_EXPAND_SZ
)
2875 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2876 else if (dwType
== REG_SZ
)
2877 strcpy (buf1
, (char *)lpval
);
2878 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2880 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2882 _putenv (strdup (buf2
));
2892 /* Rebuild system configuration to reflect invoking system. */
2893 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2895 /* Another special case: on NT, the PATH variable is actually named
2896 "Path" although cmd.exe (perhaps NT itself) arranges for
2897 environment variable lookup and setting to be case insensitive.
2898 However, Emacs assumes a fully case sensitive environment, so we
2899 need to change "Path" to "PATH" to match the expectations of
2900 various elisp packages. We do this by the sneaky method of
2901 modifying the string in the C runtime environ entry.
2903 The same applies to COMSPEC. */
2906 const char *path
= "PATH=";
2907 int path_len
= strlen (path
);
2908 const char *comspec
= "COMSPEC=";
2909 int comspec_len
= strlen (comspec
);
2911 for (envp
= environ
; *envp
; envp
++)
2912 if (_strnicmp (*envp
, path
, path_len
) == 0)
2913 memcpy (*envp
, path
, path_len
);
2914 else if (_strnicmp (*envp
, comspec
, comspec_len
) == 0)
2915 memcpy (*envp
, comspec
, comspec_len
);
2917 /* Make the same modification to `process-environment' which has
2918 already been initialized in set_initial_environment. */
2919 for (Lisp_Object env
= Vprocess_environment
; CONSP (env
); env
= XCDR (env
))
2921 Lisp_Object entry
= XCAR (env
);
2922 if (_strnicmp (SDATA (entry
), path
, path_len
) == 0)
2923 for (int i
= 0; i
< path_len
; i
++)
2924 SSET (entry
, i
, path
[i
]);
2925 else if (_strnicmp (SDATA (entry
), comspec
, comspec_len
) == 0)
2926 for (int i
= 0; i
< comspec_len
; i
++)
2927 SSET (entry
, i
, comspec
[i
]);
2931 /* Remember the initial working directory for getcwd. */
2932 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2933 Does it matter anywhere in Emacs? */
2934 if (w32_unicode_filenames
)
2936 wchar_t wstartup_dir
[MAX_PATH
];
2938 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2940 filename_from_utf16 (wstartup_dir
, startup_dir
);
2944 char astartup_dir
[MAX_PATH
];
2946 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2948 filename_from_ansi (astartup_dir
, startup_dir
);
2952 static char modname
[MAX_PATH
];
2954 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2959 /* Determine if there is a middle mouse button, to allow parse_button
2960 to decide whether right mouse events should be mouse-2 or
2962 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2967 /* Called from expand-file-name when default-directory is not a string. */
2970 emacs_root_dir (void)
2972 static char root_dir
[MAX_UTF8_PATH
];
2975 p
= getenv ("emacs_dir");
2978 filename_from_ansi (p
, root_dir
);
2979 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2980 dostounix_filename (root_dir
);
2984 /* Emulate fdutimens. */
2986 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2987 TIMESPEC[0] and TIMESPEC[1], respectively.
2988 FD must be either negative -- in which case it is ignored --
2989 or a file descriptor that is open on FILE.
2990 If FD is nonnegative, then FILE can be NULL, which means
2991 use just futimes instead of utimes.
2992 If TIMESPEC is null, FAIL.
2993 Return 0 on success, -1 (setting errno) on failure. */
2996 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
3003 if (fd
< 0 && !file
)
3008 /* _futime's prototype defines 2nd arg as having the type 'struct
3009 _utimbuf', while utime needs to accept 'struct utimbuf' for
3010 compatibility with Posix. So we need to use 2 different (but
3011 equivalent) types to avoid compiler warnings, sigh. */
3014 struct _utimbuf _ut
;
3016 _ut
.actime
= timespec
[0].tv_sec
;
3017 _ut
.modtime
= timespec
[1].tv_sec
;
3018 return _futime (fd
, &_ut
);
3024 ut
.actime
= timespec
[0].tv_sec
;
3025 ut
.modtime
= timespec
[1].tv_sec
;
3026 /* Call 'utime', which is implemented below, not the MS library
3027 function, which fails on directories. */
3028 return utime (file
, &ut
);
3033 /* ------------------------------------------------------------------------- */
3034 /* IO support and wrapper functions for the Windows API. */
3035 /* ------------------------------------------------------------------------- */
3037 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3038 on network directories, so we handle that case here.
3039 (Ulrich Leodolter, 1/11/95). */
3041 sys_ctime (const time_t *t
)
3043 char *str
= (char *) ctime (t
);
3044 return (str
? str
: (char *)"Sun Jan 01 00:00:00 1970");
3047 /* Emulate sleep...we could have done this with a define, but that
3048 would necessitate including windows.h in the files that used it.
3049 This is much easier. */
3051 sys_sleep (int seconds
)
3053 Sleep (seconds
* 1000);
3056 /* Internal MSVC functions for low-level descriptor munging */
3057 extern int __cdecl
_set_osfhnd (int fd
, long h
);
3058 extern int __cdecl
_free_osfhnd (int fd
);
3060 /* parallel array of private info on file handles */
3061 filedesc fd_info
[ MAXDESC
];
3063 typedef struct volume_info_data
{
3064 struct volume_info_data
* next
;
3066 /* time when info was obtained */
3069 /* actual volume info */
3078 /* Global referenced by various functions. */
3079 static volume_info_data volume_info
;
3081 /* Vector to indicate which drives are local and fixed (for which cached
3082 data never expires). */
3083 static BOOL fixed_drives
[26];
3085 /* Consider cached volume information to be stale if older than 10s,
3086 at least for non-local drives. Info for fixed drives is never stale. */
3087 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3088 #define VOLINFO_STILL_VALID( root_dir, info ) \
3089 ( ( isalpha (root_dir[0]) && \
3090 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3091 || GetTickCount () - info->timestamp < 10000 )
3093 /* Cache support functions. */
3095 /* Simple linked list with linear search is sufficient. */
3096 static volume_info_data
*volume_cache
= NULL
;
3098 static volume_info_data
*
3099 lookup_volume_info (char * root_dir
)
3101 volume_info_data
* info
;
3103 for (info
= volume_cache
; info
; info
= info
->next
)
3104 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
3110 add_volume_info (char * root_dir
, volume_info_data
* info
)
3112 info
->root_dir
= xstrdup (root_dir
);
3113 unixtodos_filename (info
->root_dir
);
3114 info
->next
= volume_cache
;
3115 volume_cache
= info
;
3119 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3120 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3121 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3122 static volume_info_data
*
3123 GetCachedVolumeInformation (char * root_dir
)
3125 volume_info_data
* info
;
3126 char default_root
[ MAX_UTF8_PATH
];
3127 char name
[MAX_PATH
+1];
3128 char type
[MAX_PATH
+1];
3130 /* NULL for root_dir means use root from current directory. */
3131 if (root_dir
== NULL
)
3133 if (w32_unicode_filenames
)
3135 wchar_t curdirw
[MAX_PATH
];
3137 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3139 filename_from_utf16 (curdirw
, default_root
);
3143 char curdira
[MAX_PATH
];
3145 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3147 filename_from_ansi (curdira
, default_root
);
3149 parse_root (default_root
, (const char **)&root_dir
);
3151 root_dir
= default_root
;
3154 /* Local fixed drives can be cached permanently. Removable drives
3155 cannot be cached permanently, since the volume name and serial
3156 number (if nothing else) can change. Remote drives should be
3157 treated as if they are removable, since there is no sure way to
3158 tell whether they are or not. Also, the UNC association of drive
3159 letters mapped to remote volumes can be changed at any time (even
3160 by other processes) without notice.
3162 As a compromise, so we can benefit from caching info for remote
3163 volumes, we use a simple expiry mechanism to invalidate cache
3164 entries that are more than ten seconds old. */
3167 /* No point doing this, because WNetGetConnection is even slower than
3168 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3169 GetDriveType is about the only call of this type which does not
3170 involve network access, and so is extremely quick). */
3172 /* Map drive letter to UNC if remote. */
3173 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3175 char remote_name
[ 256 ];
3176 char drive
[3] = { root_dir
[0], ':' };
3178 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3180 /* do something */ ;
3184 info
= lookup_volume_info (root_dir
);
3186 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3192 /* Info is not cached, or is stale. */
3193 if (w32_unicode_filenames
)
3195 wchar_t root_w
[MAX_PATH
];
3196 wchar_t name_w
[MAX_PATH
+1];
3197 wchar_t type_w
[MAX_PATH
+1];
3199 filename_to_utf16 (root_dir
, root_w
);
3200 if (!GetVolumeInformationW (root_w
,
3201 name_w
, sizeof (name_w
),
3205 type_w
, sizeof (type_w
)))
3207 /* Hmm... not really 100% correct, as these 2 are not file
3209 filename_from_utf16 (name_w
, name
);
3210 filename_from_utf16 (type_w
, type
);
3214 char root_a
[MAX_PATH
];
3215 char name_a
[MAX_PATH
+1];
3216 char type_a
[MAX_PATH
+1];
3218 filename_to_ansi (root_dir
, root_a
);
3219 if (!GetVolumeInformationA (root_a
,
3220 name_a
, sizeof (name_a
),
3224 type_a
, sizeof (type_a
)))
3226 filename_from_ansi (name_a
, name
);
3227 filename_from_ansi (type_a
, type
);
3230 /* Cache the volume information for future use, overwriting existing
3231 entry if present. */
3234 info
= xmalloc (sizeof (volume_info_data
));
3235 add_volume_info (root_dir
, info
);
3243 info
->name
= xstrdup (name
);
3244 unixtodos_filename (info
->name
);
3245 info
->serialnum
= serialnum
;
3246 info
->maxcomp
= maxcomp
;
3247 info
->flags
= flags
;
3248 info
->type
= xstrdup (type
);
3249 info
->timestamp
= GetTickCount ();
3255 /* Get information on the volume where NAME is held; set path pointer to
3256 start of pathname in NAME (past UNC header\volume header if present),
3257 if pPath is non-NULL.
3259 Note: if NAME includes symlinks, the information is for the volume
3260 of the symlink, not of its target. That's because, even though
3261 GetVolumeInformation returns information about the symlink target
3262 of its argument, we only pass the root directory to
3263 GetVolumeInformation, not the full NAME. */
3265 get_volume_info (const char * name
, const char ** pPath
)
3267 char temp
[MAX_UTF8_PATH
];
3268 char *rootname
= NULL
; /* default to current volume */
3269 volume_info_data
* info
;
3270 int root_len
= parse_root (name
, pPath
);
3275 /* Copy the root name of the volume, if given. */
3278 strncpy (temp
, name
, root_len
);
3279 temp
[root_len
] = '\0';
3280 unixtodos_filename (temp
);
3284 info
= GetCachedVolumeInformation (rootname
);
3287 /* Set global referenced by other functions. */
3288 volume_info
= *info
;
3294 /* Determine if volume is FAT format (ie. only supports short 8.3
3295 names); also set path pointer to start of pathname in name, if
3296 pPath is non-NULL. */
3298 is_fat_volume (const char * name
, const char ** pPath
)
3300 if (get_volume_info (name
, pPath
))
3301 return (volume_info
.maxcomp
== 12);
3305 /* Convert all slashes in a filename to backslashes, and map filename
3306 to a valid 8.3 name if necessary. The result is a pointer to a
3307 static buffer, so CAVEAT EMPTOR! */
3308 const char *map_w32_filename (const char *, const char **);
3311 map_w32_filename (const char * name
, const char ** pPath
)
3313 static char shortname
[MAX_UTF8_PATH
];
3314 char * str
= shortname
;
3317 const char * save_name
= name
;
3319 if (strlen (name
) >= sizeof (shortname
))
3321 /* Return a filename which will cause callers to fail. */
3322 strcpy (shortname
, "?");
3326 if (!fatal_error_in_progress
/* disable fancy processing during crash */
3327 && is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3329 register int left
= 8; /* maximum number of chars in part */
3330 register int extn
= 0; /* extension added? */
3331 register int dots
= 2; /* maximum number of dots allowed */
3334 *str
++ = *name
++; /* skip past UNC header */
3336 while ((c
= *name
++))
3343 *str
++ = (c
== ':' ? ':' : '\\');
3344 extn
= 0; /* reset extension flags */
3345 dots
= 2; /* max 2 dots */
3346 left
= 8; /* max length 8 for main part */
3351 /* Convert path components of the form .xxx to _xxx,
3352 but leave . and .. as they are. This allows .emacs
3353 to be read as _emacs, for example. */
3357 IS_DIRECTORY_SEP (*name
))
3372 extn
= 1; /* we've got an extension */
3373 left
= 3; /* 3 chars in extension */
3377 /* any embedded dots after the first are converted to _ */
3382 case '#': /* don't lose these, they're important */
3384 str
[-1] = c
; /* replace last character of part */
3388 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3390 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3392 dots
= 0; /* started a path component */
3401 strcpy (shortname
, name
);
3402 unixtodos_filename (shortname
);
3406 *pPath
= shortname
+ (path
- save_name
);
3412 is_exec (const char * name
)
3414 char * p
= strrchr (name
, '.');
3417 && (xstrcasecmp (p
, ".exe") == 0 ||
3418 xstrcasecmp (p
, ".com") == 0 ||
3419 xstrcasecmp (p
, ".bat") == 0 ||
3420 xstrcasecmp (p
, ".cmd") == 0));
3423 /* Emulate the Unix directory procedures opendir, closedir, and
3424 readdir. We rename them to sys_* names because some versions of
3425 MinGW startup code call opendir and readdir to glob wildcards, and
3426 the code that calls them doesn't grok UTF-8 encoded file names we
3427 produce in dirent->d_name[]. */
3429 struct dirent dir_static
; /* simulated directory contents */
3430 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3431 static int dir_is_fat
;
3432 static char dir_pathname
[MAX_UTF8_PATH
];
3433 static WIN32_FIND_DATAW dir_find_data_w
;
3434 static WIN32_FIND_DATAA dir_find_data_a
;
3435 #define DIR_FIND_DATA_W 1
3436 #define DIR_FIND_DATA_A 2
3437 static int last_dir_find_data
= -1;
3439 /* Support shares on a network resource as subdirectories of a read-only
3441 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3442 static HANDLE
open_unc_volume (const char *);
3443 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3444 static void close_unc_volume (HANDLE
);
3447 sys_opendir (const char *filename
)
3451 /* Opening is done by FindFirstFile. However, a read is inherent to
3452 this operation, so we defer the open until read time. */
3454 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3456 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3459 /* Note: We don't support traversal of UNC volumes via symlinks.
3460 Doing so would mean punishing 99.99% of use cases by resolving
3461 all the possible symlinks in FILENAME, recursively. */
3462 if (is_unc_volume (filename
))
3464 wnet_enum_handle
= open_unc_volume (filename
);
3465 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3469 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3476 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3477 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3478 /* Note: We don't support symlinks to file names on FAT volumes.
3479 Doing so would mean punishing 99.99% of use cases by resolving
3480 all the possible symlinks in FILENAME, recursively. */
3481 dir_is_fat
= is_fat_volume (filename
, NULL
);
3487 sys_closedir (DIR *dirp
)
3489 /* If we have a find-handle open, close it. */
3490 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3492 FindClose (dir_find_handle
);
3493 dir_find_handle
= INVALID_HANDLE_VALUE
;
3495 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3497 close_unc_volume (wnet_enum_handle
);
3498 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3500 xfree ((char *) dirp
);
3504 sys_readdir (DIR *dirp
)
3506 int downcase
= !NILP (Vw32_downcase_file_names
);
3508 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3510 if (!read_unc_volume (wnet_enum_handle
,
3511 dir_find_data_w
.cFileName
,
3512 dir_find_data_a
.cFileName
,
3516 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3517 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3519 char filename
[MAX_UTF8_PATH
];
3521 bool last_slash
= true;
3523 /* Note: We don't need to worry about dir_pathname being longer
3524 than MAX_UTF8_PATH, as sys_opendir already took care of that
3525 when it called map_w32_filename: that function will put a "?"
3526 in its return value in that case, thus failing all the calls
3528 strcpy (filename
, dir_pathname
);
3529 ln
= strlen (filename
);
3530 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3533 /* Note: No need to resolve symlinks in FILENAME, because
3534 FindFirst opens the directory that is the target of a
3536 if (w32_unicode_filenames
)
3538 wchar_t fnw
[MAX_PATH
+ 2];
3540 filename_to_utf16 (filename
, fnw
);
3542 wcscat (fnw
, L
"\\");
3544 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3548 char fna
[MAX_PATH
+ 2];
3550 filename_to_ansi (filename
, fna
);
3554 /* If FILENAME is not representable by the current ANSI
3555 codepage, we don't want FindFirstFileA to interpret the
3556 '?' characters as a wildcard. */
3557 if (_mbspbrk (fna
, "?"))
3558 dir_find_handle
= INVALID_HANDLE_VALUE
;
3560 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3563 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3565 /* Any changes in the value of errno here should be in sync
3566 with what directory_files_internal does when it calls
3568 switch (GetLastError ())
3570 /* Windows uses this value when FindFirstFile finds no
3571 files that match the wildcard. This is not supposed
3572 to happen, since our wildcard is "*", but just in
3573 case, if there's some weird empty directory with not
3574 even "." and ".." entries... */
3575 case ERROR_FILE_NOT_FOUND
:
3580 case ERROR_ACCESS_DENIED
:
3581 case ERROR_NETWORK_ACCESS_DENIED
:
3584 case ERROR_PATH_NOT_FOUND
:
3585 case ERROR_INVALID_DRIVE
:
3586 case ERROR_NOT_READY
:
3587 case ERROR_BAD_NETPATH
:
3588 case ERROR_BAD_NET_NAME
:
3595 else if (w32_unicode_filenames
)
3597 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3605 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3612 /* Emacs never uses this value, so don't bother making it match
3613 value returned by stat(). */
3614 dir_static
.d_ino
= 1;
3616 if (w32_unicode_filenames
)
3618 if (downcase
|| dir_is_fat
)
3620 wchar_t tem
[MAX_PATH
];
3622 wcscpy (tem
, dir_find_data_w
.cFileName
);
3624 filename_from_utf16 (tem
, dir_static
.d_name
);
3627 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3628 last_dir_find_data
= DIR_FIND_DATA_W
;
3634 /* If the file name in cFileName[] includes `?' characters, it
3635 means the original file name used characters that cannot be
3636 represented by the current ANSI codepage. To avoid total
3637 lossage, retrieve the short 8+3 alias of the long file
3639 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3641 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3642 /* 8+3 aliases are returned in all caps, which could break
3643 various alists that look at filenames' extensions. */
3646 else if (downcase
|| dir_is_fat
)
3647 strcpy (tem
, dir_find_data_a
.cFileName
);
3649 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3650 if (downcase
|| dir_is_fat
)
3653 filename_from_ansi (tem
, dir_static
.d_name
);
3655 last_dir_find_data
= DIR_FIND_DATA_A
;
3658 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3659 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3660 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3666 open_unc_volume (const char *path
)
3668 const char *fn
= map_w32_filename (path
, NULL
);
3672 if (w32_unicode_filenames
)
3675 wchar_t fnw
[MAX_PATH
];
3677 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3678 nrw
.dwType
= RESOURCETYPE_DISK
;
3679 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3680 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3681 nrw
.lpLocalName
= NULL
;
3682 filename_to_utf16 (fn
, fnw
);
3683 nrw
.lpRemoteName
= fnw
;
3684 nrw
.lpComment
= NULL
;
3685 nrw
.lpProvider
= NULL
;
3687 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3688 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3695 nra
.dwScope
= RESOURCE_GLOBALNET
;
3696 nra
.dwType
= RESOURCETYPE_DISK
;
3697 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3698 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3699 nra
.lpLocalName
= NULL
;
3700 filename_to_ansi (fn
, fna
);
3701 nra
.lpRemoteName
= fna
;
3702 nra
.lpComment
= NULL
;
3703 nra
.lpProvider
= NULL
;
3705 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3706 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3708 if (result
== NO_ERROR
)
3712 /* Make sure directory_files_internal reports a sensible error. */
3714 return INVALID_HANDLE_VALUE
;
3719 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3724 DWORD bufsize
= 512;
3728 if (w32_unicode_filenames
)
3733 buffer
= alloca (bufsize
);
3734 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3735 if (result
!= NO_ERROR
)
3737 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3738 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3740 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3742 wcsncpy (fname_w
, ptrw
, size
);
3747 int dbcs_p
= max_filename_mbslen () > 1;
3750 buffer
= alloca (bufsize
);
3751 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3752 if (result
!= NO_ERROR
)
3754 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3757 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3760 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3761 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3764 strncpy (fname_a
, ptra
, size
);
3772 close_unc_volume (HANDLE henum
)
3774 if (henum
!= INVALID_HANDLE_VALUE
)
3775 WNetCloseEnum (henum
);
3779 unc_volume_file_attributes (const char *path
)
3784 henum
= open_unc_volume (path
);
3785 if (henum
== INVALID_HANDLE_VALUE
)
3788 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3790 close_unc_volume (henum
);
3795 /* Ensure a network connection is authenticated. */
3797 logon_network_drive (const char *path
)
3799 char share
[MAX_UTF8_PATH
];
3806 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3807 drvtype
= DRIVE_REMOTE
;
3808 else if (path
[0] == '\0' || path
[1] != ':')
3809 drvtype
= GetDriveType (NULL
);
3816 drvtype
= GetDriveType (drive
);
3819 /* Only logon to networked drives. */
3820 if (drvtype
!= DRIVE_REMOTE
)
3824 strncpy (share
, path
, MAX_UTF8_PATH
);
3825 /* Truncate to just server and share name. */
3826 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3828 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3835 if (w32_unicode_filenames
)
3837 NETRESOURCEW resourcew
;
3838 wchar_t share_w
[MAX_PATH
];
3840 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3841 resourcew
.dwType
= RESOURCETYPE_DISK
;
3842 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3843 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3844 resourcew
.lpLocalName
= NULL
;
3845 filename_to_utf16 (share
, share_w
);
3846 resourcew
.lpRemoteName
= share_w
;
3847 resourcew
.lpProvider
= NULL
;
3849 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3853 NETRESOURCEA resourcea
;
3854 char share_a
[MAX_PATH
];
3856 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3857 resourcea
.dwType
= RESOURCETYPE_DISK
;
3858 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3859 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3860 resourcea
.lpLocalName
= NULL
;
3861 filename_to_ansi (share
, share_a
);
3862 resourcea
.lpRemoteName
= share_a
;
3863 resourcea
.lpProvider
= NULL
;
3865 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3871 case ERROR_ALREADY_ASSIGNED
:
3873 case ERROR_ACCESS_DENIED
:
3874 case ERROR_LOGON_FAILURE
:
3880 case ERROR_BAD_NET_NAME
:
3881 case ERROR_NO_NET_OR_BAD_PATH
:
3882 case ERROR_NO_NETWORK
:
3883 case ERROR_CANCELLED
:
3890 /* Emulate faccessat(2). */
3892 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3895 char fullname
[MAX_UTF8_PATH
];
3897 /* Rely on a hack: an open directory is modeled as file descriptor 0,
3898 and its actual file name is stored in dir_pathname by opendir.
3899 This is good enough for the current usage in Emacs, but is fragile. */
3900 if (dirfd
!= AT_FDCWD
3901 && !(IS_DIRECTORY_SEP (path
[0])
3902 || IS_DEVICE_SEP (path
[1])))
3904 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
3906 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
3907 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", path
)
3910 errno
= ENAMETOOLONG
;
3916 /* When dired.c calls us with F_OK and a trailing slash, it actually
3917 wants to know whether PATH is a directory. */
3918 if (IS_DIRECTORY_SEP (path
[strlen (path
) - 1]) && mode
== F_OK
)
3921 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3922 newer versions blow up when passed D_OK. */
3923 path
= map_w32_filename (path
, NULL
);
3924 /* If the last element of PATH is a symlink, we need to resolve it
3925 to get the attributes of its target file. Note: any symlinks in
3926 PATH elements other than the last one are transparently resolved
3927 by GetFileAttributes below. */
3928 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3929 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3930 path
= chase_symlinks (path
);
3932 if (w32_unicode_filenames
)
3934 wchar_t path_w
[MAX_PATH
];
3936 filename_to_utf16 (path
, path_w
);
3937 attributes
= GetFileAttributesW (path_w
);
3941 char path_a
[MAX_PATH
];
3943 filename_to_ansi (path
, path_a
);
3944 attributes
= GetFileAttributesA (path_a
);
3947 if (attributes
== -1)
3949 DWORD w32err
= GetLastError ();
3953 case ERROR_INVALID_NAME
:
3954 case ERROR_BAD_PATHNAME
:
3955 if (is_unc_volume (path
))
3957 attributes
= unc_volume_file_attributes (path
);
3958 if (attributes
== -1)
3967 case ERROR_FILE_NOT_FOUND
:
3968 case ERROR_BAD_NETPATH
:
3979 if ((mode
& X_OK
) != 0
3980 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3985 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3990 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3998 /* A special test for DIRNAME being a directory accessible by the
3999 current user. This is needed because the security permissions in
4000 directory's ACLs are not visible in the Posix-style mode bits
4001 returned by 'stat' and in attributes returned by GetFileAttributes.
4002 So a directory would seem like it's readable by the current user,
4003 but will in fact error out with EACCES when they actually try. */
4005 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
4007 char pattern
[MAX_UTF8_PATH
];
4008 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
4011 /* Network volumes need a different reading method. */
4012 if (is_unc_volume (dirname
))
4014 void *read_result
= NULL
;
4015 wchar_t fnw
[MAX_PATH
];
4018 dh
= open_unc_volume (dirname
);
4019 if (dh
!= INVALID_HANDLE_VALUE
)
4021 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
4022 close_unc_volume (dh
);
4024 /* Treat empty volumes as accessible. */
4025 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
4028 /* Note: map_w32_filename makes sure DIRNAME is not longer than
4030 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
4032 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
4033 opens the directory that is the target of a symlink. */
4034 if (w32_unicode_filenames
)
4036 wchar_t pat_w
[MAX_PATH
+ 2];
4037 WIN32_FIND_DATAW dfd_w
;
4039 filename_to_utf16 (pattern
, pat_w
);
4041 wcscat (pat_w
, L
"\\");
4042 wcscat (pat_w
, L
"*");
4043 dh
= FindFirstFileW (pat_w
, &dfd_w
);
4047 char pat_a
[MAX_PATH
+ 2];
4048 WIN32_FIND_DATAA dfd_a
;
4050 filename_to_ansi (pattern
, pat_a
);
4052 strcpy (pat_a
, "\\");
4053 strcat (pat_a
, "*");
4054 /* In case DIRNAME cannot be expressed in characters from the
4055 current ANSI codepage. */
4056 if (_mbspbrk (pat_a
, "?"))
4057 dh
= INVALID_HANDLE_VALUE
;
4059 dh
= FindFirstFileA (pat_a
, &dfd_a
);
4062 if (dh
== INVALID_HANDLE_VALUE
)
4068 /* A version of 'access' to be used locally with file names in
4069 locale-specific encoding. Does not resolve symlinks and does not
4070 support file names on FAT12 and FAT16 volumes, but that's OK, since
4071 we only invoke this function for files inside the Emacs source or
4072 installation tree, on directories (so any symlinks should have the
4073 directory bit set), and on short file names such as "C:/.emacs". */
4075 sys_access (const char *fname
, int mode
)
4077 char fname_copy
[MAX_PATH
], *p
;
4080 strcpy (fname_copy
, fname
);
4081 /* Do the equivalent of unixtodos_filename. */
4082 for (p
= fname_copy
; *p
; p
= CharNext (p
))
4086 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
4088 DWORD w32err
= GetLastError ();
4092 case ERROR_INVALID_NAME
:
4093 case ERROR_BAD_PATHNAME
:
4094 case ERROR_FILE_NOT_FOUND
:
4095 case ERROR_BAD_NETPATH
:
4104 if ((mode
& X_OK
) != 0
4105 && !(is_exec (fname_copy
)
4106 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4111 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4116 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4124 /* Shadow some MSVC runtime functions to map requests for long filenames
4125 to reasonable short names if necessary. This was originally added to
4126 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4130 sys_chdir (const char * path
)
4132 path
= map_w32_filename (path
, NULL
);
4133 if (w32_unicode_filenames
)
4135 wchar_t newdir_w
[MAX_PATH
];
4137 if (filename_to_utf16 (path
, newdir_w
) == 0)
4138 return _wchdir (newdir_w
);
4143 char newdir_a
[MAX_PATH
];
4145 if (filename_to_ansi (path
, newdir_a
) == 0)
4146 return _chdir (newdir_a
);
4152 sys_chmod (const char * path
, int mode
)
4154 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4155 if (w32_unicode_filenames
)
4157 wchar_t path_w
[MAX_PATH
];
4159 filename_to_utf16 (path
, path_w
);
4160 return _wchmod (path_w
, mode
);
4164 char path_a
[MAX_PATH
];
4166 filename_to_ansi (path
, path_a
);
4167 return _chmod (path_a
, mode
);
4172 sys_creat (const char * path
, int mode
)
4174 path
= map_w32_filename (path
, NULL
);
4175 if (w32_unicode_filenames
)
4177 wchar_t path_w
[MAX_PATH
];
4179 filename_to_utf16 (path
, path_w
);
4180 return _wcreat (path_w
, mode
);
4184 char path_a
[MAX_PATH
];
4186 filename_to_ansi (path
, path_a
);
4187 return _creat (path_a
, mode
);
4192 sys_fopen (const char * path
, const char * mode
)
4196 const char * mode_save
= mode
;
4198 /* Force all file handles to be non-inheritable. This is necessary to
4199 ensure child processes don't unwittingly inherit handles that might
4200 prevent future file access. */
4204 else if (mode
[0] == 'w' || mode
[0] == 'a')
4205 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4209 /* Only do simplistic option parsing. */
4213 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4216 else if (mode
[0] == 'b')
4221 else if (mode
[0] == 't')
4228 path
= map_w32_filename (path
, NULL
);
4229 if (w32_unicode_filenames
)
4231 wchar_t path_w
[MAX_PATH
];
4233 filename_to_utf16 (path
, path_w
);
4234 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4238 char path_a
[MAX_PATH
];
4240 filename_to_ansi (path
, path_a
);
4241 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4246 return _fdopen (fd
, mode_save
);
4249 /* This only works on NTFS volumes, but is useful to have. */
4251 sys_link (const char * old
, const char * new)
4255 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4256 wchar_t oldname_w
[MAX_PATH
];
4257 char oldname_a
[MAX_PATH
];
4259 if (old
== NULL
|| new == NULL
)
4265 strcpy (oldname
, map_w32_filename (old
, NULL
));
4266 strcpy (newname
, map_w32_filename (new, NULL
));
4268 if (w32_unicode_filenames
)
4270 filename_to_utf16 (oldname
, oldname_w
);
4271 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4272 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4276 filename_to_ansi (oldname
, oldname_a
);
4277 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4278 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4280 if (fileh
!= INVALID_HANDLE_VALUE
)
4284 /* Confusingly, the "alternate" stream name field does not apply
4285 when restoring a hard link, and instead contains the actual
4286 stream data for the link (ie. the name of the link to create).
4287 The WIN32_STREAM_ID structure before the cStreamName field is
4288 the stream header, which is then immediately followed by the
4292 WIN32_STREAM_ID wid
;
4293 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4296 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4297 indicates that flag is unsupported for CP_UTF8, and OTOH says
4298 it is the default anyway. */
4299 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4300 data
.wid
.cStreamName
, MAX_PATH
);
4303 LPVOID context
= NULL
;
4306 data
.wid
.dwStreamId
= BACKUP_LINK
;
4307 data
.wid
.dwStreamAttributes
= 0;
4308 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4309 data
.wid
.Size
.HighPart
= 0;
4310 data
.wid
.dwStreamNameSize
= 0;
4312 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4313 offsetof (WIN32_STREAM_ID
, cStreamName
)
4314 + data
.wid
.Size
.LowPart
,
4315 &wbytes
, FALSE
, FALSE
, &context
)
4316 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4323 DWORD err
= GetLastError ();
4328 case ERROR_ACCESS_DENIED
:
4329 /* This is what happens when OLDNAME is a directory,
4330 since Windows doesn't support hard links to
4331 directories. Posix says to set errno to EPERM in
4333 if (w32_unicode_filenames
)
4334 attributes
= GetFileAttributesW (oldname_w
);
4336 attributes
= GetFileAttributesA (oldname_a
);
4337 if (attributes
!= -1
4338 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4340 else if (attributes
== -1
4341 && is_unc_volume (oldname
)
4342 && unc_volume_file_attributes (oldname
) != -1)
4347 case ERROR_TOO_MANY_LINKS
:
4350 case ERROR_NOT_SAME_DEVICE
:
4360 CloseHandle (fileh
);
4369 sys_mkdir (const char * path
, mode_t mode
)
4371 path
= map_w32_filename (path
, NULL
);
4373 if (w32_unicode_filenames
)
4375 wchar_t path_w
[MAX_PATH
];
4377 filename_to_utf16 (path
, path_w
);
4378 return _wmkdir (path_w
);
4382 char path_a
[MAX_PATH
];
4384 filename_to_ansi (path
, path_a
);
4385 return _mkdir (path_a
);
4390 sys_open (const char * path
, int oflag
, int mode
)
4392 const char* mpath
= map_w32_filename (path
, NULL
);
4395 if (w32_unicode_filenames
)
4397 wchar_t mpath_w
[MAX_PATH
];
4399 filename_to_utf16 (mpath
, mpath_w
);
4400 /* If possible, try to open file without _O_CREAT, to be able to
4401 write to existing hidden and system files. Force all file
4402 handles to be non-inheritable. */
4403 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4404 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4406 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4410 char mpath_a
[MAX_PATH
];
4412 filename_to_ansi (mpath
, mpath_a
);
4413 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4414 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4416 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4423 fchmod (int fd
, mode_t mode
)
4429 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4432 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4435 bool have_temp_a
= false;
4437 /* MoveFile on Windows 95 doesn't correctly change the short file name
4438 alias in a number of circumstances (it is not easy to predict when
4439 just by looking at oldname and newname, unfortunately). In these
4440 cases, renaming through a temporary name avoids the problem.
4442 A second problem on Windows 95 is that renaming through a temp name when
4443 newname is uppercase fails (the final long name ends up in
4444 lowercase, although the short alias might be uppercase) UNLESS the
4445 long temp name is not 8.3.
4447 So, on Windows 95 we always rename through a temp name, and we make sure
4448 the temp name has a long extension to ensure correct renaming. */
4450 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4452 /* volume_info is set indirectly by map_w32_filename. */
4453 oldname_dev
= volume_info
.serialnum
;
4455 if (os_subtype
== OS_9X
)
4460 char oldname_a
[MAX_PATH
];
4462 oldname
= map_w32_filename (oldname
, NULL
);
4463 filename_to_ansi (oldname
, oldname_a
);
4464 filename_to_ansi (temp
, temp_a
);
4465 if ((o
= strrchr (oldname_a
, '\\')))
4468 o
= (char *) oldname_a
;
4470 if ((p
= strrchr (temp_a
, '\\')))
4477 /* Force temp name to require a manufactured 8.3 alias - this
4478 seems to make the second rename work properly. */
4479 sprintf (p
, "_.%s.%d", o
, i
);
4481 result
= rename (oldname_a
, temp_a
);
4483 /* This loop must surely terminate! */
4484 while (result
< 0 && errno
== EEXIST
);
4490 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4491 (at least if it is a file; don't do this for directories).
4493 Since we mustn't do this if we are just changing the case of the
4494 file name (we would end up deleting the file we are trying to
4495 rename!), we let rename detect if the destination file already
4496 exists - that way we avoid the possible pitfalls of trying to
4497 determine ourselves whether two names really refer to the same
4498 file, which is not always possible in the general case. (Consider
4499 all the permutations of shared or subst'd drives, etc.) */
4501 newname
= map_w32_filename (newname
, NULL
);
4503 /* volume_info is set indirectly by map_w32_filename. */
4504 newname_dev
= volume_info
.serialnum
;
4506 if (w32_unicode_filenames
)
4508 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4510 filename_to_utf16 (temp
, temp_w
);
4511 filename_to_utf16 (newname
, newname_w
);
4512 result
= _wrename (temp_w
, newname_w
);
4515 DWORD w32err
= GetLastError ();
4518 && newname_dev
!= oldname_dev
)
4521 /* The implementation of `rename' on Windows does not return
4522 errno = EXDEV when you are moving a directory to a
4523 different storage device (ex. logical disk). It returns
4524 EACCES instead. So here we handle such situations and
4526 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4527 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4530 else if (errno
== EEXIST
&& force
)
4532 DWORD attributes_old
;
4533 DWORD attributes_new
;
4535 if (_wchmod (newname_w
, 0666) != 0)
4537 attributes_old
= GetFileAttributesW (temp_w
);
4538 attributes_new
= GetFileAttributesW (newname_w
);
4539 if (attributes_old
!= -1 && attributes_new
!= -1
4540 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4541 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4543 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4549 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4551 if (_wrmdir (newname_w
) != 0)
4554 else if (_wunlink (newname_w
) != 0)
4556 result
= _wrename (temp_w
, newname_w
);
4558 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4559 && is_symlink (temp
))
4561 /* This is Windows prohibiting the user from creating a
4562 symlink in another place, since that requires
4570 char newname_a
[MAX_PATH
];
4573 filename_to_ansi (temp
, temp_a
);
4574 filename_to_ansi (newname
, newname_a
);
4575 result
= rename (temp_a
, newname_a
);
4578 DWORD w32err
= GetLastError ();
4581 && newname_dev
!= oldname_dev
)
4584 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4585 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4588 else if (errno
== EEXIST
&& force
)
4590 DWORD attributes_old
;
4591 DWORD attributes_new
;
4593 if (_chmod (newname_a
, 0666) != 0)
4595 attributes_old
= GetFileAttributesA (temp_a
);
4596 attributes_new
= GetFileAttributesA (newname_a
);
4597 if (attributes_old
!= -1 && attributes_new
!= -1
4598 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4599 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4601 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4607 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4609 if (_rmdir (newname_a
) != 0)
4612 else if (_unlink (newname_a
) != 0)
4614 result
= rename (temp_a
, newname_a
);
4616 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4617 && is_symlink (temp
))
4626 sys_rename (char const *old
, char const *new)
4628 return sys_rename_replace (old
, new, TRUE
);
4632 sys_rmdir (const char * path
)
4634 path
= map_w32_filename (path
, NULL
);
4636 if (w32_unicode_filenames
)
4638 wchar_t path_w
[MAX_PATH
];
4640 filename_to_utf16 (path
, path_w
);
4641 return _wrmdir (path_w
);
4645 char path_a
[MAX_PATH
];
4647 filename_to_ansi (path
, path_a
);
4648 return _rmdir (path_a
);
4653 sys_unlink (const char * path
)
4657 path
= map_w32_filename (path
, NULL
);
4659 if (w32_unicode_filenames
)
4661 wchar_t path_w
[MAX_PATH
];
4663 filename_to_utf16 (path
, path_w
);
4664 /* On Unix, unlink works without write permission. */
4665 _wchmod (path_w
, 0666);
4666 rmstatus
= _wunlink (path_w
);
4668 /* Symlinks to directories can only be deleted by _rmdir;
4669 _unlink returns EACCES. */
4672 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4673 rmstatus
= _wrmdir (path_w
);
4679 char path_a
[MAX_PATH
];
4681 filename_to_ansi (path
, path_a
);
4682 _chmod (path_a
, 0666);
4683 rmstatus
= _unlink (path_a
);
4687 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4688 rmstatus
= _rmdir (path_a
);
4696 static FILETIME utc_base_ft
;
4697 static ULONGLONG utc_base
; /* In 100ns units */
4698 static int init
= 0;
4700 #define FILETIME_TO_U64(result, ft) \
4702 ULARGE_INTEGER uiTemp; \
4703 uiTemp.LowPart = (ft).dwLowDateTime; \
4704 uiTemp.HighPart = (ft).dwHighDateTime; \
4705 result = uiTemp.QuadPart; \
4709 initialize_utc_base (void)
4711 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4720 st
.wMilliseconds
= 0;
4722 SystemTimeToFileTime (&st
, &utc_base_ft
);
4723 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4727 convert_time (FILETIME ft
)
4733 initialize_utc_base ();
4737 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4740 FILETIME_TO_U64 (tmp
, ft
);
4741 return (time_t) ((tmp
- utc_base
) / 10000000L);
4745 convert_from_time_t (time_t time
, FILETIME
* pft
)
4751 initialize_utc_base ();
4755 /* time in 100ns units since 1-Jan-1601 */
4756 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4757 pft
->dwHighDateTime
= tmp
.HighPart
;
4758 pft
->dwLowDateTime
= tmp
.LowPart
;
4761 static PSECURITY_DESCRIPTOR
4762 get_file_security_desc_by_handle (HANDLE h
)
4764 PSECURITY_DESCRIPTOR psd
= NULL
;
4766 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4767 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4769 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4770 NULL
, NULL
, NULL
, NULL
, &psd
);
4771 if (err
!= ERROR_SUCCESS
)
4777 static PSECURITY_DESCRIPTOR
4778 get_file_security_desc_by_name (const char *fname
)
4780 PSECURITY_DESCRIPTOR psd
= NULL
;
4782 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4783 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4785 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4787 err
= GetLastError ();
4788 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4792 psd
= xmalloc (sd_len
);
4793 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4805 unsigned n_subauthorities
;
4807 /* Use the last sub-authority value of the RID, the relative
4808 portion of the SID, as user/group ID. */
4809 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4810 if (n_subauthorities
< 1)
4811 return 0; /* the "World" RID */
4812 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4815 /* Caching SID and account values for faster lokup. */
4819 struct w32_id
*next
;
4821 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4824 static struct w32_id
*w32_idlist
;
4827 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4829 struct w32_id
*tail
, *found
;
4831 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4833 if (equal_sid ((PSID
)tail
->sid
, sid
))
4842 strcpy (name
, found
->name
);
4850 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4853 struct w32_id
*new_entry
;
4855 /* We don't want to leave behind stale cache from when Emacs was
4859 sid_len
= get_length_sid (sid
);
4860 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4863 new_entry
->rid
= id
;
4864 strcpy (new_entry
->name
, name
);
4865 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4866 new_entry
->next
= w32_idlist
;
4867 w32_idlist
= new_entry
;
4876 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4880 SID_NAME_USE ignore
;
4882 DWORD name_len
= sizeof (name
);
4884 DWORD domain_len
= sizeof (domain
);
4889 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4890 else if (what
== GID
)
4891 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4895 if (!result
|| !is_valid_sid (sid
))
4897 else if (!w32_cached_id (sid
, id
, nm
))
4899 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4900 domain
, &domain_len
, &ignore
)
4901 || name_len
> UNLEN
+1)
4905 *id
= get_rid (sid
);
4907 w32_add_to_cache (sid
, *id
, name
);
4914 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4916 int dflt_usr
= 0, dflt_grp
= 0;
4925 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4927 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4930 /* Consider files to belong to current user/group, if we cannot get
4931 more accurate information. */
4934 st
->st_uid
= dflt_passwd
.pw_uid
;
4935 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4939 st
->st_gid
= dflt_passwd
.pw_gid
;
4940 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4944 /* Return non-zero if NAME is a potentially slow filesystem. */
4945 int is_slow_fs (const char *);
4948 is_slow_fs (const char *name
)
4953 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4954 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4955 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4956 devtype
= GetDriveType (NULL
); /* use root of current drive */
4959 /* GetDriveType needs the root directory of the drive. */
4960 strncpy (drive_root
, name
, 2);
4961 drive_root
[2] = '\\';
4962 drive_root
[3] = '\0';
4963 devtype
= GetDriveType (drive_root
);
4965 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4968 /* If this is non-zero, the caller wants accurate information about
4969 file's owner and group, which could be expensive to get. dired.c
4970 uses this flag when needed for the job at hand. */
4971 int w32_stat_get_owner_group
;
4973 /* MSVC stat function can't cope with UNC names and has other bugs, so
4974 replace it with our own. This also allows us to calculate consistent
4975 inode values and owner/group without hacks in the main Emacs code,
4976 and support file names encoded in UTF-8. */
4979 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4981 char *name
, *save_name
, *r
;
4982 WIN32_FIND_DATAW wfd_w
;
4983 WIN32_FIND_DATAA wfd_a
;
4985 unsigned __int64 fake_inode
= 0;
4988 int rootdir
= FALSE
;
4989 PSECURITY_DESCRIPTOR psd
= NULL
;
4990 int is_a_symlink
= 0;
4991 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4992 DWORD access_rights
= 0;
4993 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4994 FILETIME ctime
, atime
, wtime
;
4995 wchar_t name_w
[MAX_PATH
];
4996 char name_a
[MAX_PATH
];
4998 if (path
== NULL
|| buf
== NULL
)
5004 save_name
= name
= (char *) map_w32_filename (path
, &path
);
5005 /* Must be valid filename, no wild cards or other invalid
5007 if (strpbrk (name
, "*?|<>\""))
5013 len
= strlen (name
);
5014 /* Allocate 1 extra byte so that we could append a slash to a root
5015 directory, down below. */
5016 name
= strcpy (alloca (len
+ 2), name
);
5018 /* Avoid a somewhat costly call to is_symlink if the filesystem
5019 doesn't support symlinks. */
5020 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5021 is_a_symlink
= is_symlink (name
);
5023 /* Plan A: Open the file and get all the necessary information via
5024 the resulting handle. This solves several issues in one blow:
5026 . retrieves attributes for the target of a symlink, if needed
5027 . gets attributes of root directories and symlinks pointing to
5028 root directories, thus avoiding the need for special-casing
5029 these and detecting them by examining the file-name format
5030 . retrieves more accurate attributes (e.g., non-zero size for
5031 some directories, esp. directories that are junction points)
5032 . correctly resolves "c:/..", "/.." and similar file names
5033 . avoids run-time penalties for 99% of use cases
5035 Plan A is always tried first, unless the user asked not to (but
5036 if the file is a symlink and we need to follow links, we try Plan
5037 A even if the user asked not to).
5039 If Plan A fails, we go to Plan B (below), where various
5040 potentially expensive techniques must be used to handle "special"
5041 files such as UNC volumes etc. */
5042 if (!(NILP (Vw32_get_true_file_attributes
)
5043 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
5044 /* Following symlinks requires getting the info by handle. */
5045 || (is_a_symlink
&& follow_symlinks
))
5047 BY_HANDLE_FILE_INFORMATION info
;
5049 if (is_a_symlink
&& !follow_symlinks
)
5050 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
5051 /* READ_CONTROL access rights are required to get security info
5052 by handle. But if the OS doesn't support security in the
5053 first place, we don't need to try. */
5054 if (is_windows_9x () != TRUE
)
5055 access_rights
|= READ_CONTROL
;
5057 if (w32_unicode_filenames
)
5059 filename_to_utf16 (name
, name_w
);
5060 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5062 /* If CreateFile fails with READ_CONTROL, try again with
5063 zero as access rights. */
5064 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5065 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
5070 filename_to_ansi (name
, name_a
);
5071 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5073 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5074 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
5077 if (fh
== INVALID_HANDLE_VALUE
)
5078 goto no_true_file_attributes
;
5080 /* This is more accurate in terms of getting the correct number
5081 of links, but is quite slow (it is noticeable when Emacs is
5082 making a list of file name completions). */
5083 if (GetFileInformationByHandle (fh
, &info
))
5085 nlinks
= info
.nNumberOfLinks
;
5086 /* Might as well use file index to fake inode values, but this
5087 is not guaranteed to be unique unless we keep a handle open
5088 all the time (even then there are situations where it is
5089 not unique). Reputedly, there are at most 48 bits of info
5090 (on NTFS, presumably less on FAT). */
5091 fake_inode
= info
.nFileIndexHigh
;
5093 fake_inode
+= info
.nFileIndexLow
;
5094 serialnum
= info
.dwVolumeSerialNumber
;
5095 fs_high
= info
.nFileSizeHigh
;
5096 fs_low
= info
.nFileSizeLow
;
5097 ctime
= info
.ftCreationTime
;
5098 atime
= info
.ftLastAccessTime
;
5099 wtime
= info
.ftLastWriteTime
;
5100 fattrs
= info
.dwFileAttributes
;
5104 /* We don't go to Plan B here, because it's not clear that
5105 it's a good idea. The only known use case where
5106 CreateFile succeeds, but GetFileInformationByHandle fails
5107 (with ERROR_INVALID_FUNCTION) is for character devices
5108 such as NUL, PRN, etc. For these, switching to Plan B is
5109 a net loss, because we lose the character device
5110 attribute returned by GetFileType below (FindFirstFile
5111 doesn't set that bit in the attributes), and the other
5112 fields don't make sense for character devices anyway.
5113 Emacs doesn't really care for non-file entities in the
5114 context of l?stat, so neither do we. */
5116 /* w32err is assigned so one could put a breakpoint here and
5117 examine its value, when GetFileInformationByHandle
5119 DWORD w32err
= GetLastError ();
5123 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5129 /* Test for a symlink before testing for a directory, since
5130 symlinks to directories have the directory bit set, but we
5131 don't want them to appear as directories. */
5132 if (is_a_symlink
&& !follow_symlinks
)
5133 buf
->st_mode
= S_IFLNK
;
5134 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5135 buf
->st_mode
= S_IFDIR
;
5138 DWORD ftype
= GetFileType (fh
);
5142 case FILE_TYPE_DISK
:
5143 buf
->st_mode
= S_IFREG
;
5145 case FILE_TYPE_PIPE
:
5146 buf
->st_mode
= S_IFIFO
;
5148 case FILE_TYPE_CHAR
:
5149 case FILE_TYPE_UNKNOWN
:
5151 buf
->st_mode
= S_IFCHR
;
5154 /* We produce the fallback owner and group data, based on the
5155 current user that runs Emacs, in the following cases:
5157 . caller didn't request owner and group info
5158 . this is Windows 9X
5159 . getting security by handle failed, and we need to produce
5160 information for the target of a symlink (this is better
5161 than producing a potentially misleading info about the
5164 If getting security by handle fails, and we don't need to
5165 resolve symlinks, we try getting security by name. */
5166 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5167 get_file_owner_and_group (NULL
, buf
);
5170 psd
= get_file_security_desc_by_handle (fh
);
5173 get_file_owner_and_group (psd
, buf
);
5176 else if (!(is_a_symlink
&& follow_symlinks
))
5178 psd
= get_file_security_desc_by_name (name
);
5179 get_file_owner_and_group (psd
, buf
);
5183 get_file_owner_and_group (NULL
, buf
);
5189 no_true_file_attributes
:
5190 /* Plan B: Either getting a handle on the file failed, or the
5191 caller explicitly asked us to not bother making this
5192 information more accurate.
5194 Implementation note: In Plan B, we never bother to resolve
5195 symlinks, even if we got here because we tried Plan A and
5196 failed. That's because, even if the caller asked for extra
5197 precision by setting Vw32_get_true_file_attributes to t,
5198 resolving symlinks requires acquiring a file handle to the
5199 symlink, which we already know will fail. And if the user
5200 did not ask for extra precision, resolving symlinks will fly
5201 in the face of that request, since the user then wants the
5202 lightweight version of the code. */
5203 rootdir
= (path
>= save_name
+ len
- 1
5204 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5206 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5207 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5208 if (IS_DIRECTORY_SEP (r
[0])
5209 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5212 /* Note: If NAME is a symlink to the root of a UNC volume
5213 (i.e. "\\SERVER"), we will not detect that here, and we will
5214 return data about the symlink as result of FindFirst below.
5215 This is unfortunate, but that marginal use case does not
5216 justify a call to chase_symlinks which would impose a penalty
5217 on all the other use cases. (We get here for symlinks to
5218 roots of UNC volumes because CreateFile above fails for them,
5219 unlike with symlinks to root directories X:\ of drives.) */
5220 if (is_unc_volume (name
))
5222 fattrs
= unc_volume_file_attributes (name
);
5226 ctime
= atime
= wtime
= utc_base_ft
;
5230 /* Make sure root directories end in a slash. */
5231 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5232 strcpy (name
+ len
, "\\");
5233 if (GetDriveType (name
) < 2)
5239 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5240 ctime
= atime
= wtime
= utc_base_ft
;
5246 /* Make sure non-root directories do NOT end in a slash,
5247 otherwise FindFirstFile might fail. */
5248 if (IS_DIRECTORY_SEP (name
[len
-1]))
5251 /* (This is hacky, but helps when doing file completions on
5252 network drives.) Optimize by using information available from
5253 active readdir if possible. */
5254 len
= strlen (dir_pathname
);
5255 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5257 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5258 && last_dir_find_data
!= -1
5259 && !(is_a_symlink
&& follow_symlinks
)
5260 /* The 2 file-name comparisons below support only ASCII
5261 characters, and will lose (compare not equal) when
5262 the file names include non-ASCII characters that are
5263 the same but for the case. However, doing this
5264 properly involves: (a) converting both file names to
5265 UTF-16, (b) lower-casing both names using CharLowerW,
5266 and (c) comparing the results; this would be quite a
5267 bit slower, whereas Plan B is for users who want
5268 lightweight albeit inaccurate version of 'stat'. */
5269 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5270 && IS_DIRECTORY_SEP (name
[len
])
5271 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5273 have_wfd
= last_dir_find_data
;
5274 /* This was the last entry returned by readdir. */
5275 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5276 wfd_w
= dir_find_data_w
;
5278 wfd_a
= dir_find_data_a
;
5282 logon_network_drive (name
);
5284 if (w32_unicode_filenames
)
5286 filename_to_utf16 (name
, name_w
);
5287 fh
= FindFirstFileW (name_w
, &wfd_w
);
5288 have_wfd
= DIR_FIND_DATA_W
;
5292 filename_to_ansi (name
, name_a
);
5293 /* If NAME includes characters not representable by
5294 the current ANSI codepage, filename_to_ansi
5295 usually replaces them with a '?'. We don't want
5296 to let FindFirstFileA interpret those as wildcards,
5297 and "succeed", returning us data from some random
5298 file in the same directory. */
5299 if (_mbspbrk (name_a
, "?"))
5300 fh
= INVALID_HANDLE_VALUE
;
5302 fh
= FindFirstFileA (name_a
, &wfd_a
);
5303 have_wfd
= DIR_FIND_DATA_A
;
5305 if (fh
== INVALID_HANDLE_VALUE
)
5312 /* Note: if NAME is a symlink, the information we get from
5313 FindFirstFile is for the symlink, not its target. */
5314 if (have_wfd
== DIR_FIND_DATA_W
)
5316 fattrs
= wfd_w
.dwFileAttributes
;
5317 ctime
= wfd_w
.ftCreationTime
;
5318 atime
= wfd_w
.ftLastAccessTime
;
5319 wtime
= wfd_w
.ftLastWriteTime
;
5320 fs_high
= wfd_w
.nFileSizeHigh
;
5321 fs_low
= wfd_w
.nFileSizeLow
;
5325 fattrs
= wfd_a
.dwFileAttributes
;
5326 ctime
= wfd_a
.ftCreationTime
;
5327 atime
= wfd_a
.ftLastAccessTime
;
5328 wtime
= wfd_a
.ftLastWriteTime
;
5329 fs_high
= wfd_a
.nFileSizeHigh
;
5330 fs_low
= wfd_a
.nFileSizeLow
;
5334 serialnum
= volume_info
.serialnum
;
5336 if (is_a_symlink
&& !follow_symlinks
)
5337 buf
->st_mode
= S_IFLNK
;
5338 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5339 buf
->st_mode
= S_IFDIR
;
5341 buf
->st_mode
= S_IFREG
;
5343 get_file_owner_and_group (NULL
, buf
);
5346 buf
->st_ino
= fake_inode
;
5348 buf
->st_dev
= serialnum
;
5349 buf
->st_rdev
= serialnum
;
5351 buf
->st_size
= fs_high
;
5352 buf
->st_size
<<= 32;
5353 buf
->st_size
+= fs_low
;
5354 buf
->st_nlink
= nlinks
;
5356 /* Convert timestamps to Unix format. */
5357 buf
->st_mtime
= convert_time (wtime
);
5358 buf
->st_atime
= convert_time (atime
);
5359 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5360 buf
->st_ctime
= convert_time (ctime
);
5361 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5363 /* determine rwx permissions */
5364 if (is_a_symlink
&& !follow_symlinks
)
5365 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5368 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5369 permission
= S_IREAD
;
5371 permission
= S_IREAD
| S_IWRITE
;
5373 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5374 permission
|= S_IEXEC
;
5375 else if (is_exec (name
))
5376 permission
|= S_IEXEC
;
5379 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5385 stat (const char * path
, struct stat
* buf
)
5387 return stat_worker (path
, buf
, 1);
5391 lstat (const char * path
, struct stat
* buf
)
5393 return stat_worker (path
, buf
, 0);
5397 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5399 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5400 This is good enough for the current usage in Emacs, but is fragile.
5402 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5403 Gnulib does this and can serve as a model. */
5404 char fullname
[MAX_UTF8_PATH
];
5408 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5410 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5411 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5414 errno
= ENAMETOOLONG
;
5420 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5423 /* Provide fstat and utime as well as stat for consistent handling of
5426 fstat (int desc
, struct stat
* buf
)
5428 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5429 BY_HANDLE_FILE_INFORMATION info
;
5430 unsigned __int64 fake_inode
;
5433 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5435 case FILE_TYPE_DISK
:
5436 buf
->st_mode
= S_IFREG
;
5437 if (!GetFileInformationByHandle (fh
, &info
))
5443 case FILE_TYPE_PIPE
:
5444 buf
->st_mode
= S_IFIFO
;
5446 case FILE_TYPE_CHAR
:
5447 case FILE_TYPE_UNKNOWN
:
5449 buf
->st_mode
= S_IFCHR
;
5451 memset (&info
, 0, sizeof (info
));
5452 info
.dwFileAttributes
= 0;
5453 info
.ftCreationTime
= utc_base_ft
;
5454 info
.ftLastAccessTime
= utc_base_ft
;
5455 info
.ftLastWriteTime
= utc_base_ft
;
5458 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5459 buf
->st_mode
= S_IFDIR
;
5461 buf
->st_nlink
= info
.nNumberOfLinks
;
5462 /* Might as well use file index to fake inode values, but this
5463 is not guaranteed to be unique unless we keep a handle open
5464 all the time (even then there are situations where it is
5465 not unique). Reputedly, there are at most 48 bits of info
5466 (on NTFS, presumably less on FAT). */
5467 fake_inode
= info
.nFileIndexHigh
;
5469 fake_inode
+= info
.nFileIndexLow
;
5471 /* MSVC defines _ino_t to be short; other libc's might not. */
5472 if (sizeof (buf
->st_ino
) == 2)
5473 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5475 buf
->st_ino
= fake_inode
;
5477 /* If the caller so requested, get the true file owner and group.
5478 Otherwise, consider the file to belong to the current user. */
5479 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5480 get_file_owner_and_group (NULL
, buf
);
5483 PSECURITY_DESCRIPTOR psd
= NULL
;
5485 psd
= get_file_security_desc_by_handle (fh
);
5488 get_file_owner_and_group (psd
, buf
);
5492 get_file_owner_and_group (NULL
, buf
);
5495 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5496 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5498 buf
->st_size
= info
.nFileSizeHigh
;
5499 buf
->st_size
<<= 32;
5500 buf
->st_size
+= info
.nFileSizeLow
;
5502 /* Convert timestamps to Unix format. */
5503 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5504 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5505 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5506 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5507 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5509 /* determine rwx permissions */
5510 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5511 permission
= S_IREAD
;
5513 permission
= S_IREAD
| S_IWRITE
;
5515 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5516 permission
|= S_IEXEC
;
5519 #if 0 /* no way of knowing the filename */
5520 char * p
= strrchr (name
, '.');
5522 (xstrcasecmp (p
, ".exe") == 0 ||
5523 xstrcasecmp (p
, ".com") == 0 ||
5524 xstrcasecmp (p
, ".bat") == 0 ||
5525 xstrcasecmp (p
, ".cmd") == 0))
5526 permission
|= S_IEXEC
;
5530 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5535 /* A version of 'utime' which handles directories as well as
5539 utime (const char *name
, struct utimbuf
*times
)
5541 struct utimbuf deftime
;
5548 deftime
.modtime
= deftime
.actime
= time (NULL
);
5552 if (w32_unicode_filenames
)
5554 wchar_t name_utf16
[MAX_PATH
];
5556 if (filename_to_utf16 (name
, name_utf16
) != 0)
5557 return -1; /* errno set by filename_to_utf16 */
5559 /* Need write access to set times. */
5560 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5561 /* If NAME specifies a directory, FILE_SHARE_DELETE
5562 allows other processes to delete files inside it,
5563 while we have the directory open. */
5564 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5565 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5569 char name_ansi
[MAX_PATH
];
5571 if (filename_to_ansi (name
, name_ansi
) != 0)
5572 return -1; /* errno set by filename_to_ansi */
5574 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5575 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5576 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5578 if (fh
!= INVALID_HANDLE_VALUE
)
5580 convert_from_time_t (times
->actime
, &atime
);
5581 convert_from_time_t (times
->modtime
, &mtime
);
5582 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5592 DWORD err
= GetLastError ();
5596 case ERROR_FILE_NOT_FOUND
:
5597 case ERROR_PATH_NOT_FOUND
:
5598 case ERROR_INVALID_DRIVE
:
5599 case ERROR_BAD_NETPATH
:
5600 case ERROR_DEV_NOT_EXIST
:
5601 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5602 file name includes ?s, i.e. translation to ANSI failed. */
5603 case ERROR_INVALID_NAME
:
5606 case ERROR_TOO_MANY_OPEN_FILES
:
5609 case ERROR_ACCESS_DENIED
:
5610 case ERROR_SHARING_VIOLATION
:
5623 sys_umask (int mode
)
5625 static int current_mask
;
5626 int retval
, arg
= 0;
5628 /* The only bit we really support is the write bit. Files are
5629 always readable on MS-Windows, and the execute bit does not exist
5631 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5632 to prevent access by other users on NTFS. */
5633 if ((mode
& S_IWRITE
) != 0)
5636 retval
= _umask (arg
);
5637 /* Merge into the return value the bits they've set the last time,
5638 which msvcrt.dll ignores and never returns. Emacs insists on its
5639 notion of mask being identical to what we return. */
5640 retval
|= (current_mask
& ~S_IWRITE
);
5641 current_mask
= mode
;
5647 /* Symlink-related functions. */
5648 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5649 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5653 symlink (char const *filename
, char const *linkname
)
5655 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5657 int dir_access
, filename_ends_in_slash
;
5659 /* Diagnostics follows Posix as much as possible. */
5660 if (filename
== NULL
|| linkname
== NULL
)
5670 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5672 errno
= ENAMETOOLONG
;
5676 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5677 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5683 /* Note: since empty FILENAME was already rejected, we can safely
5684 refer to FILENAME[1]. */
5685 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5687 /* Non-absolute FILENAME is understood as being relative to
5688 LINKNAME's directory. We need to prepend that directory to
5689 FILENAME to get correct results from faccessat below, since
5690 otherwise it will interpret FILENAME relative to the
5691 directory where the Emacs process runs. Note that
5692 make-symbolic-link always makes sure LINKNAME is a fully
5693 expanded file name. */
5694 char tem
[MAX_UTF8_PATH
];
5695 char *p
= linkfn
+ strlen (linkfn
);
5697 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5700 strncpy (tem
, linkfn
, p
- linkfn
);
5701 strcpy (tem
+ (p
- linkfn
), filename
);
5702 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5705 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5707 /* Since Windows distinguishes between symlinks to directories and
5708 to files, we provide a kludgy feature: if FILENAME doesn't
5709 exist, but ends in a slash, we create a symlink to directory. If
5710 FILENAME exists and is a directory, we always create a symlink to
5712 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5713 if (dir_access
== 0 || filename_ends_in_slash
)
5714 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5716 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5717 if (filename_ends_in_slash
)
5718 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5721 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5723 /* ENOSYS is set by create_symbolic_link, when it detects that
5724 the OS doesn't support the CreateSymbolicLink API. */
5725 if (errno
!= ENOSYS
)
5727 DWORD w32err
= GetLastError ();
5731 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5732 TGTFN point to the same file name, go figure. */
5734 case ERROR_FILE_EXISTS
:
5737 case ERROR_ACCESS_DENIED
:
5740 case ERROR_FILE_NOT_FOUND
:
5741 case ERROR_PATH_NOT_FOUND
:
5742 case ERROR_BAD_NETPATH
:
5743 case ERROR_INVALID_REPARSE_DATA
:
5746 case ERROR_DIRECTORY
:
5749 case ERROR_PRIVILEGE_NOT_HELD
:
5750 case ERROR_NOT_ALL_ASSIGNED
:
5753 case ERROR_DISK_FULL
:
5766 /* A quick inexpensive test of whether FILENAME identifies a file that
5767 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5768 must already be in the normalized form returned by
5769 map_w32_filename. If the symlink is to a directory, the
5770 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5772 Note: for repeated operations on many files, it is best to test
5773 whether the underlying volume actually supports symlinks, by
5774 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5775 avoid the call to this function if it doesn't. That's because the
5776 call to GetFileAttributes takes a non-negligible time, especially
5777 on non-local or removable filesystems. See stat_worker for an
5778 example of how to do that. */
5780 is_symlink (const char *filename
)
5783 wchar_t filename_w
[MAX_PATH
];
5784 char filename_a
[MAX_PATH
];
5785 WIN32_FIND_DATAW wfdw
;
5786 WIN32_FIND_DATAA wfda
;
5788 int attrs_mean_symlink
;
5790 if (w32_unicode_filenames
)
5792 filename_to_utf16 (filename
, filename_w
);
5793 attrs
= GetFileAttributesW (filename_w
);
5797 filename_to_ansi (filename
, filename_a
);
5798 attrs
= GetFileAttributesA (filename_a
);
5802 DWORD w32err
= GetLastError ();
5806 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5808 case ERROR_ACCESS_DENIED
:
5811 case ERROR_FILE_NOT_FOUND
:
5812 case ERROR_PATH_NOT_FOUND
:
5819 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5821 logon_network_drive (filename
);
5822 if (w32_unicode_filenames
)
5824 fh
= FindFirstFileW (filename_w
, &wfdw
);
5825 attrs_mean_symlink
=
5826 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5827 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5828 if (attrs_mean_symlink
)
5829 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5831 else if (_mbspbrk (filename_a
, "?"))
5833 /* filename_to_ansi failed to convert the file name. */
5839 fh
= FindFirstFileA (filename_a
, &wfda
);
5840 attrs_mean_symlink
=
5841 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5842 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5843 if (attrs_mean_symlink
)
5844 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5846 if (fh
== INVALID_HANDLE_VALUE
)
5849 return attrs_mean_symlink
;
5852 /* If NAME identifies a symbolic link, copy into BUF the file name of
5853 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5854 null-terminate the target name, even if it fits. Return the number
5855 of bytes copied, or -1 if NAME is not a symlink or any error was
5856 encountered while resolving it. The file name copied into BUF is
5857 encoded in the current ANSI codepage. */
5859 readlink (const char *name
, char *buf
, size_t buf_size
)
5862 TOKEN_PRIVILEGES privs
;
5863 int restore_privs
= 0;
5866 char resolved
[MAX_UTF8_PATH
];
5879 path
= map_w32_filename (name
, NULL
);
5881 if (strlen (path
) > MAX_UTF8_PATH
)
5883 errno
= ENAMETOOLONG
;
5888 if (is_windows_9x () == TRUE
5889 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5890 || !is_symlink (path
))
5893 errno
= EINVAL
; /* not a symlink */
5897 /* Done with simple tests, now we're in for some _real_ work. */
5898 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5900 /* Implementation note: From here and onward, don't return early,
5901 since that will fail to restore the original set of privileges of
5902 the calling thread. */
5904 retval
= -1; /* not too optimistic, are we? */
5906 /* Note: In the next call to CreateFile, we use zero as the 2nd
5907 argument because, when the symlink is a hidden/system file,
5908 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5909 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5910 and directory symlinks. */
5911 if (w32_unicode_filenames
)
5913 wchar_t path_w
[MAX_PATH
];
5915 filename_to_utf16 (path
, path_w
);
5916 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5917 FILE_FLAG_OPEN_REPARSE_POINT
5918 | FILE_FLAG_BACKUP_SEMANTICS
,
5923 char path_a
[MAX_PATH
];
5925 filename_to_ansi (path
, path_a
);
5926 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5927 FILE_FLAG_OPEN_REPARSE_POINT
5928 | FILE_FLAG_BACKUP_SEMANTICS
,
5931 if (sh
!= INVALID_HANDLE_VALUE
)
5933 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5934 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5937 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5938 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5941 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5945 /* Copy the link target name, in wide characters, from
5946 reparse_data, then convert it to multibyte encoding in
5947 the current locale's codepage. */
5951 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5953 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5954 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5955 size_t size_to_copy
= buf_size
;
5957 /* According to MSDN, PrintNameLength does not include the
5958 terminating null character. */
5959 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5960 memcpy (lwname
, lwname_src
, lwname_len
);
5961 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5962 filename_from_utf16 (lwname
, resolved
);
5963 dostounix_filename (resolved
);
5964 lname_size
= strlen (resolved
) + 1;
5965 if (lname_size
<= buf_size
)
5966 size_to_copy
= lname_size
;
5967 strncpy (buf
, resolved
, size_to_copy
);
5969 retval
= size_to_copy
;
5975 /* CreateFile failed. */
5976 DWORD w32err2
= GetLastError ();
5980 case ERROR_FILE_NOT_FOUND
:
5981 case ERROR_PATH_NOT_FOUND
:
5984 case ERROR_ACCESS_DENIED
:
5985 case ERROR_TOO_MANY_OPEN_FILES
:
5995 restore_privilege (&privs
);
6003 readlinkat (int fd
, char const *name
, char *buffer
,
6006 /* Rely on a hack: an open directory is modeled as file descriptor 0,
6007 as in fstatat. FIXME: Add proper support for readlinkat. */
6008 char fullname
[MAX_UTF8_PATH
];
6012 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
6015 errno
= ENAMETOOLONG
;
6021 return readlink (name
, buffer
, buffer_size
);
6024 /* If FILE is a symlink, return its target (stored in a static
6025 buffer); otherwise return FILE.
6027 This function repeatedly resolves symlinks in the last component of
6028 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6029 until it arrives at a file whose last component is not a symlink,
6030 or some error occurs. It returns the target of the last
6031 successfully resolved symlink in the chain. If it succeeds to
6032 resolve even a single symlink, the value returned is an absolute
6033 file name with backslashes (result of GetFullPathName). By
6034 contrast, if the original FILE is returned, it is unaltered.
6036 Note: This function can set errno even if it succeeds.
6038 Implementation note: we only resolve the last portion ("basename")
6039 of the argument FILE and of each following file in the chain,
6040 disregarding any possible symlinks in its leading directories.
6041 This is because Windows system calls and library functions
6042 transparently resolve symlinks in leading directories and return
6043 correct information, as long as the basename is not a symlink. */
6045 chase_symlinks (const char *file
)
6047 static char target
[MAX_UTF8_PATH
];
6048 char link
[MAX_UTF8_PATH
];
6049 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
6050 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
6051 ssize_t res
, link_len
;
6054 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
6055 return (char *)file
;
6057 if (w32_unicode_filenames
)
6059 wchar_t file_w
[MAX_PATH
];
6061 filename_to_utf16 (file
, file_w
);
6062 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
6063 return (char *)file
;
6064 filename_from_utf16 (link_w
, link
);
6068 char file_a
[MAX_PATH
];
6070 filename_to_ansi (file
, file_a
);
6071 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
6072 return (char *)file
;
6073 filename_from_ansi (link_a
, link
);
6075 link_len
= strlen (link
);
6080 /* Remove trailing slashes, as we want to resolve the last
6081 non-trivial part of the link name. */
6082 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
6083 link
[link_len
--] = '\0';
6085 res
= readlink (link
, target
, MAX_UTF8_PATH
);
6089 if (!(IS_DEVICE_SEP (target
[1])
6090 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
6092 /* Target is relative. Append it to the directory part of
6093 the symlink, then copy the result back to target. */
6094 char *p
= link
+ link_len
;
6096 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
6099 strcpy (target
, link
);
6101 /* Resolve any "." and ".." to get a fully-qualified file name
6103 if (w32_unicode_filenames
)
6105 filename_to_utf16 (target
, target_w
);
6106 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
6108 filename_from_utf16 (link_w
, link
);
6112 filename_to_ansi (target
, target_a
);
6113 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
6115 filename_from_ansi (link_a
, link
);
6117 link_len
= strlen (link
);
6119 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6121 if (loop_count
> 100)
6124 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6125 return (char *)file
;
6130 /* Posix ACL emulation. */
6133 acl_valid (acl_t acl
)
6135 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6139 acl_to_text (acl_t acl
, ssize_t
*size
)
6142 SECURITY_INFORMATION flags
=
6143 OWNER_SECURITY_INFORMATION
|
6144 GROUP_SECURITY_INFORMATION
|
6145 DACL_SECURITY_INFORMATION
;
6146 char *retval
= NULL
;
6152 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6155 /* We don't want to mix heaps, so we duplicate the string in our
6156 heap and free the one allocated by the API. */
6157 retval
= xstrdup (str_acl
);
6160 LocalFree (str_acl
);
6162 else if (errno
!= ENOTSUP
)
6169 acl_from_text (const char *acl_str
)
6171 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6177 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6180 retval
= xmalloc (sd_size
);
6181 memcpy (retval
, psd
, sd_size
);
6184 else if (errno
!= ENOTSUP
)
6191 acl_free (void *ptr
)
6198 acl_get_file (const char *fname
, acl_type_t type
)
6200 PSECURITY_DESCRIPTOR psd
= NULL
;
6201 const char *filename
;
6203 if (type
== ACL_TYPE_ACCESS
)
6206 SECURITY_INFORMATION si
=
6207 OWNER_SECURITY_INFORMATION
|
6208 GROUP_SECURITY_INFORMATION
|
6209 DACL_SECURITY_INFORMATION
;
6212 filename
= map_w32_filename (fname
, NULL
);
6213 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6214 fname
= chase_symlinks (filename
);
6219 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6220 && errno
!= ENOTSUP
)
6222 err
= GetLastError ();
6223 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6225 psd
= xmalloc (sd_len
);
6226 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6233 else if (err
== ERROR_FILE_NOT_FOUND
6234 || err
== ERROR_PATH_NOT_FOUND
6235 /* ERROR_INVALID_NAME is what we get if
6236 w32-unicode-filenames is nil and the file cannot
6237 be encoded in the current ANSI codepage. */
6238 || err
== ERROR_INVALID_NAME
)
6246 else if (type
!= ACL_TYPE_DEFAULT
)
6253 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6255 TOKEN_PRIVILEGES old1
, old2
;
6257 int st
= 0, retval
= -1;
6258 SECURITY_INFORMATION flags
= 0;
6259 PSID psidOwner
, psidGroup
;
6264 const char *filename
;
6266 if (acl_valid (acl
) != 0
6267 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6273 if (type
== ACL_TYPE_DEFAULT
)
6279 filename
= map_w32_filename (fname
, NULL
);
6280 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6281 fname
= chase_symlinks (filename
);
6285 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6288 flags
|= OWNER_SECURITY_INFORMATION
;
6289 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6292 flags
|= GROUP_SECURITY_INFORMATION
;
6293 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6296 flags
|= DACL_SECURITY_INFORMATION
;
6300 /* According to KB-245153, setting the owner will succeed if either:
6301 (1) the caller is the user who will be the new owner, and has the
6302 SE_TAKE_OWNERSHIP privilege, or
6303 (2) the caller has the SE_RESTORE privilege, in which case she can
6304 set any valid user or group as the owner
6306 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6307 privileges, and disregard any failures in obtaining them. If
6308 these privileges cannot be obtained, and do not already exist in
6309 the calling thread's security token, this function could fail
6311 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6313 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6318 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6319 DACL inheritance is involved, but it seems to preserve ownership
6320 better than SetNamedSecurityInfo, which is important e.g., in
6322 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6324 err
= GetLastError ();
6326 if (errno
!= ENOTSUP
)
6327 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6328 psidOwner
, psidGroup
, pacl
, NULL
);
6331 err
= ERROR_SUCCESS
;
6332 if (err
!= ERROR_SUCCESS
)
6334 if (errno
== ENOTSUP
)
6336 else if (err
== ERROR_INVALID_OWNER
6337 || err
== ERROR_NOT_ALL_ASSIGNED
6338 || err
== ERROR_ACCESS_DENIED
)
6340 /* Maybe the requested ACL and the one the file already has
6341 are identical, in which case we can silently ignore the
6342 failure. (And no, Windows doesn't.) */
6343 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6348 char *acl_from
= acl_to_text (current_acl
, NULL
);
6349 char *acl_to
= acl_to_text (acl
, NULL
);
6351 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6357 acl_free (acl_from
);
6360 acl_free (current_acl
);
6363 else if (err
== ERROR_FILE_NOT_FOUND
6364 || err
== ERROR_PATH_NOT_FOUND
6365 /* ERROR_INVALID_NAME is what we get if
6366 w32-unicode-filenames is nil and the file cannot be
6367 encoded in the current ANSI codepage. */
6368 || err
== ERROR_INVALID_NAME
)
6382 restore_privilege (&old2
);
6383 restore_privilege (&old1
);
6390 /* Return true if errno value ERRNUM indicates that ACLs are well
6391 supported on this system. ERRNUM should be an errno value obtained
6392 after an ACL-related system call fails. */
6394 acl_errno_valid (int errnum
)
6408 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6409 have a fixed max size for file names, so we don't need the kind of
6410 alloc/malloc/realloc dance the gnulib version does. We also don't
6411 support FD-relative symlinks. */
6413 careadlinkat (int fd
, char const *filename
,
6414 char *buffer
, size_t buffer_size
,
6415 struct allocator
const *alloc
,
6416 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6418 char linkname
[MAX_UTF8_PATH
];
6421 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6425 char *retval
= buffer
;
6427 linkname
[link_size
++] = '\0';
6428 if (link_size
> buffer_size
)
6429 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6431 memcpy (retval
, linkname
, link_size
);
6439 w32_copy_file (const char *from
, const char *to
,
6440 int keep_time
, int preserve_ownership
, int copy_acls
)
6444 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6445 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6447 /* We ignore preserve_ownership for now. */
6448 preserve_ownership
= preserve_ownership
;
6452 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6453 if (acl
== NULL
&& acl_errno_valid (errno
))
6456 if (w32_unicode_filenames
)
6458 filename_to_utf16 (from
, from_w
);
6459 filename_to_utf16 (to
, to_w
);
6460 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6464 filename_to_ansi (from
, from_a
);
6465 filename_to_ansi (to
, to_a
);
6466 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6470 /* CopyFile doesn't set errno when it fails. By far the most
6471 "popular" reason is that the target is read-only. */
6472 DWORD err
= GetLastError ();
6476 case ERROR_FILE_NOT_FOUND
:
6479 case ERROR_ACCESS_DENIED
:
6482 case ERROR_ENCRYPTION_FAILED
:
6494 /* CopyFile retains the timestamp by default. However, see
6495 "Community Additions" for CopyFile: it sounds like that is not
6496 entirely true. Testing on Windows XP confirms that modified time
6497 is copied, but creation and last-access times are not.
6499 else if (!keep_time
)
6501 struct timespec now
;
6504 if (w32_unicode_filenames
)
6506 /* Ensure file is writable while its times are set. */
6507 attributes
= GetFileAttributesW (to_w
);
6508 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6509 now
= current_timespec ();
6510 if (set_file_times (-1, to
, now
, now
))
6512 /* Restore original attributes. */
6513 SetFileAttributesW (to_w
, attributes
);
6518 /* Restore original attributes. */
6519 SetFileAttributesW (to_w
, attributes
);
6523 attributes
= GetFileAttributesA (to_a
);
6524 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6525 now
= current_timespec ();
6526 if (set_file_times (-1, to
, now
, now
))
6528 SetFileAttributesA (to_a
, attributes
);
6533 SetFileAttributesA (to_a
, attributes
);
6539 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6541 if (fail
&& acl_errno_valid (errno
))
6549 /* Support for browsing other processes and their attributes. See
6550 process.c for the Lisp bindings. */
6552 /* Helper wrapper functions. */
6554 static HANDLE WINAPI
6555 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6557 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6559 if (g_b_init_create_toolhelp32_snapshot
== 0)
6561 g_b_init_create_toolhelp32_snapshot
= 1;
6562 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6563 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6564 "CreateToolhelp32Snapshot");
6566 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6568 return INVALID_HANDLE_VALUE
;
6570 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6574 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6576 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6578 if (g_b_init_process32_first
== 0)
6580 g_b_init_process32_first
= 1;
6581 s_pfn_Process32_First
= (Process32First_Proc
)
6582 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6585 if (s_pfn_Process32_First
== NULL
)
6589 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6593 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6595 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6597 if (g_b_init_process32_next
== 0)
6599 g_b_init_process32_next
= 1;
6600 s_pfn_Process32_Next
= (Process32Next_Proc
)
6601 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6604 if (s_pfn_Process32_Next
== NULL
)
6608 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6612 open_thread_token (HANDLE ThreadHandle
,
6613 DWORD DesiredAccess
,
6615 PHANDLE TokenHandle
)
6617 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6618 HMODULE hm_advapi32
= NULL
;
6619 if (is_windows_9x () == TRUE
)
6621 SetLastError (ERROR_NOT_SUPPORTED
);
6624 if (g_b_init_open_thread_token
== 0)
6626 g_b_init_open_thread_token
= 1;
6627 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6628 s_pfn_Open_Thread_Token
=
6629 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6631 if (s_pfn_Open_Thread_Token
== NULL
)
6633 SetLastError (ERROR_NOT_SUPPORTED
);
6637 s_pfn_Open_Thread_Token (
6646 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6648 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6649 HMODULE hm_advapi32
= NULL
;
6650 if (is_windows_9x () == TRUE
)
6654 if (g_b_init_impersonate_self
== 0)
6656 g_b_init_impersonate_self
= 1;
6657 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6658 s_pfn_Impersonate_Self
=
6659 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6661 if (s_pfn_Impersonate_Self
== NULL
)
6665 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6669 revert_to_self (void)
6671 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6672 HMODULE hm_advapi32
= NULL
;
6673 if (is_windows_9x () == TRUE
)
6677 if (g_b_init_revert_to_self
== 0)
6679 g_b_init_revert_to_self
= 1;
6680 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6681 s_pfn_Revert_To_Self
=
6682 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6684 if (s_pfn_Revert_To_Self
== NULL
)
6688 return s_pfn_Revert_To_Self ();
6692 get_process_memory_info (HANDLE h_proc
,
6693 PPROCESS_MEMORY_COUNTERS mem_counters
,
6696 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6697 HMODULE hm_psapi
= NULL
;
6698 if (is_windows_9x () == TRUE
)
6702 if (g_b_init_get_process_memory_info
== 0)
6704 g_b_init_get_process_memory_info
= 1;
6705 hm_psapi
= LoadLibrary ("Psapi.dll");
6707 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6708 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6710 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6714 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6718 get_process_working_set_size (HANDLE h_proc
,
6722 static GetProcessWorkingSetSize_Proc
6723 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6725 if (is_windows_9x () == TRUE
)
6729 if (g_b_init_get_process_working_set_size
== 0)
6731 g_b_init_get_process_working_set_size
= 1;
6732 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6733 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6734 "GetProcessWorkingSetSize");
6736 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6740 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6744 global_memory_status (MEMORYSTATUS
*buf
)
6746 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6748 if (is_windows_9x () == TRUE
)
6752 if (g_b_init_global_memory_status
== 0)
6754 g_b_init_global_memory_status
= 1;
6755 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6756 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6757 "GlobalMemoryStatus");
6759 if (s_pfn_Global_Memory_Status
== NULL
)
6763 return s_pfn_Global_Memory_Status (buf
);
6767 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6769 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6771 if (is_windows_9x () == TRUE
)
6775 if (g_b_init_global_memory_status_ex
== 0)
6777 g_b_init_global_memory_status_ex
= 1;
6778 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6779 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6780 "GlobalMemoryStatusEx");
6782 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6786 return s_pfn_Global_Memory_Status_Ex (buf
);
6790 list_system_processes (void)
6792 Lisp_Object proclist
= Qnil
;
6795 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6797 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6799 PROCESSENTRY32 proc_entry
;
6803 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6804 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6805 res
= process32_next (h_snapshot
, &proc_entry
))
6807 proc_id
= proc_entry
.th32ProcessID
;
6808 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6811 CloseHandle (h_snapshot
);
6812 proclist
= Fnreverse (proclist
);
6819 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6821 TOKEN_PRIVILEGES priv
;
6822 DWORD priv_size
= sizeof (priv
);
6823 DWORD opriv_size
= sizeof (*old_priv
);
6824 HANDLE h_token
= NULL
;
6825 HANDLE h_thread
= GetCurrentThread ();
6829 res
= open_thread_token (h_thread
,
6830 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6832 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6834 if (impersonate_self (SecurityImpersonation
))
6835 res
= open_thread_token (h_thread
,
6836 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6841 priv
.PrivilegeCount
= 1;
6842 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6843 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6844 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6845 old_priv
, &opriv_size
)
6846 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6850 CloseHandle (h_token
);
6856 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6858 DWORD priv_size
= sizeof (*priv
);
6859 HANDLE h_token
= NULL
;
6862 if (open_thread_token (GetCurrentThread (),
6863 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6866 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6867 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6871 CloseHandle (h_token
);
6877 ltime (ULONGLONG time_100ns
)
6879 ULONGLONG time_sec
= time_100ns
/ 10000000;
6880 int subsec
= time_100ns
% 10000000;
6881 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6882 subsec
/ 10, subsec
% 10 * 100000);
6885 #define U64_TO_LISP_TIME(time) ltime (time)
6888 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6889 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6892 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6893 ULONGLONG tem1
, tem2
, tem3
, tem
;
6896 || !get_process_times_fn
6897 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6898 &ft_kernel
, &ft_user
))
6901 GetSystemTimeAsFileTime (&ft_current
);
6903 FILETIME_TO_U64 (tem1
, ft_kernel
);
6904 *stime
= U64_TO_LISP_TIME (tem1
);
6906 FILETIME_TO_U64 (tem2
, ft_user
);
6907 *utime
= U64_TO_LISP_TIME (tem2
);
6910 *ttime
= U64_TO_LISP_TIME (tem3
);
6912 FILETIME_TO_U64 (tem
, ft_creation
);
6913 /* Process no 4 (System) returns zero creation time. */
6916 *ctime
= U64_TO_LISP_TIME (tem
);
6920 FILETIME_TO_U64 (tem3
, ft_current
);
6921 tem
= (tem3
- utc_base
) - tem
;
6923 *etime
= U64_TO_LISP_TIME (tem
);
6927 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6938 system_process_attributes (Lisp_Object pid
)
6940 Lisp_Object attrs
= Qnil
;
6941 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6942 HANDLE h_snapshot
, h_proc
;
6945 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6946 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6947 DWORD glength
= sizeof (gname
);
6948 HANDLE token
= NULL
;
6949 SID_NAME_USE user_type
;
6950 unsigned char *buf
= NULL
;
6952 TOKEN_USER user_token
;
6953 TOKEN_PRIMARY_GROUP group_token
;
6956 PROCESS_MEMORY_COUNTERS mem
;
6957 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6958 SIZE_T minrss
, maxrss
;
6960 MEMORY_STATUS_EX memstex
;
6961 double totphys
= 0.0;
6962 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6964 BOOL result
= FALSE
;
6966 CHECK_NUMBER_OR_FLOAT (pid
);
6967 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6969 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6971 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6976 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6977 for (res
= process32_first (h_snapshot
, &pe
); res
;
6978 res
= process32_next (h_snapshot
, &pe
))
6980 if (proc_id
== pe
.th32ProcessID
)
6983 decoded_cmd
= build_string ("Idle");
6986 /* Decode the command name from locale-specific
6988 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6991 code_convert_string_norecord (cmd_str
,
6992 Vlocale_coding_system
, 0);
6994 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6995 attrs
= Fcons (Fcons (Qppid
,
6996 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6998 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
7000 attrs
= Fcons (Fcons (Qthcount
,
7001 make_fixnum_or_float (pe
.cntThreads
)),
7008 CloseHandle (h_snapshot
);
7014 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7016 /* If we were denied a handle to the process, try again after
7017 enabling the SeDebugPrivilege in our process. */
7020 TOKEN_PRIVILEGES priv_current
;
7022 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
7024 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7026 restore_privilege (&priv_current
);
7032 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
7035 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
7036 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7038 buf
= xmalloc (blen
);
7039 result
= get_token_information (token
, TokenUser
,
7040 (LPVOID
)buf
, blen
, &needed
);
7043 memcpy (&user_token
, buf
, sizeof (user_token
));
7044 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
7046 euid
= get_rid (user_token
.User
.Sid
);
7047 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
7052 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
7055 strcpy (uname
, "unknown");
7059 ulength
= strlen (uname
);
7065 /* Determine a reasonable euid and gid values. */
7066 if (xstrcasecmp ("administrator", uname
) == 0)
7068 euid
= 500; /* well-known Administrator uid */
7069 egid
= 513; /* well-known None gid */
7073 /* Get group id and name. */
7074 result
= get_token_information (token
, TokenPrimaryGroup
,
7075 (LPVOID
)buf
, blen
, &needed
);
7076 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7078 buf
= xrealloc (buf
, blen
= needed
);
7079 result
= get_token_information (token
, TokenPrimaryGroup
,
7080 (LPVOID
)buf
, blen
, &needed
);
7084 memcpy (&group_token
, buf
, sizeof (group_token
));
7085 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
7087 egid
= get_rid (group_token
.PrimaryGroup
);
7088 dlength
= sizeof (domain
);
7090 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
7091 gname
, &glength
, NULL
, &dlength
,
7094 w32_add_to_cache (group_token
.PrimaryGroup
,
7098 strcpy (gname
, "None");
7102 glength
= strlen (gname
);
7110 if (!is_windows_9x ())
7112 /* We couldn't open the process token, presumably because of
7113 insufficient access rights. Assume this process is run
7115 strcpy (uname
, "SYSTEM");
7116 strcpy (gname
, "None");
7117 euid
= 18; /* SYSTEM */
7118 egid
= 513; /* None */
7119 glength
= strlen (gname
);
7120 ulength
= strlen (uname
);
7122 /* If we are running under Windows 9X, where security calls are
7123 not supported, we assume all processes are run by the current
7125 else if (GetUserName (uname
, &ulength
))
7127 if (xstrcasecmp ("administrator", uname
) == 0)
7132 strcpy (gname
, "None");
7133 glength
= strlen (gname
);
7134 ulength
= strlen (uname
);
7140 strcpy (uname
, "administrator");
7141 ulength
= strlen (uname
);
7142 strcpy (gname
, "None");
7143 glength
= strlen (gname
);
7146 CloseHandle (token
);
7149 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7150 tem
= make_unibyte_string (uname
, ulength
);
7151 attrs
= Fcons (Fcons (Quser
,
7152 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7154 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7155 tem
= make_unibyte_string (gname
, glength
);
7156 attrs
= Fcons (Fcons (Qgroup
,
7157 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7160 if (global_memory_status_ex (&memstex
))
7161 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7162 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7164 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7165 double, so we need to do this for it... */
7167 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7168 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7169 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7171 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7173 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7174 else if (global_memory_status (&memst
))
7175 totphys
= memst
.dwTotalPhys
/ 1024.0;
7178 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7181 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7183 attrs
= Fcons (Fcons (Qmajflt
,
7184 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7186 attrs
= Fcons (Fcons (Qvsize
,
7187 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7189 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7191 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7194 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7196 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7198 attrs
= Fcons (Fcons (Qmajflt
,
7199 make_fixnum_or_float (mem
.PageFaultCount
)),
7201 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7203 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7206 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7208 DWORD rss
= maxrss
/ 1024;
7210 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7212 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7215 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7217 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7218 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7219 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7220 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7221 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7222 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7225 /* FIXME: Retrieve command line by walking the PEB of the process. */
7228 CloseHandle (h_proc
);
7233 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7234 unsigned long long *totalswap
, unsigned long long *freeswap
)
7237 MEMORY_STATUS_EX memstex
;
7239 /* Use GlobalMemoryStatusEx if available, as it can report more than
7241 if (global_memory_status_ex (&memstex
))
7243 *totalram
= memstex
.ullTotalPhys
;
7244 *freeram
= memstex
.ullAvailPhys
;
7245 *totalswap
= memstex
.ullTotalPageFile
;
7246 *freeswap
= memstex
.ullAvailPageFile
;
7249 else if (global_memory_status (&memst
))
7251 *totalram
= memst
.dwTotalPhys
;
7252 *freeram
= memst
.dwAvailPhys
;
7253 *totalswap
= memst
.dwTotalPageFile
;
7254 *freeswap
= memst
.dwAvailPageFile
;
7262 /* Wrappers for winsock functions to map between our file descriptors
7263 and winsock's handles; also set h_errno for convenience.
7265 To allow Emacs to run on systems which don't have winsock support
7266 installed, we dynamically link to winsock on startup if present, and
7267 otherwise provide the minimum necessary functionality
7268 (eg. gethostname). */
7270 /* function pointers for relevant socket functions */
7271 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7272 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7273 int (PASCAL
*pfn_WSAGetLastError
) (void);
7274 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7275 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7276 WSANETWORKEVENTS
*NetworkEvents
);
7278 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7279 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7280 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7281 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7282 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7283 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7284 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7285 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7286 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7287 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7288 int (PASCAL
*pfn_WSACleanup
) (void);
7290 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7291 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7292 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7293 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7294 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7295 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7296 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7297 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7298 const char * optval
, int optlen
);
7299 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7300 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7302 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7303 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7304 struct sockaddr
* from
, int * fromlen
);
7305 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7306 const struct sockaddr
* to
, int tolen
);
7308 int (PASCAL
*pfn_getaddrinfo
) (const char *, const char *,
7309 const struct addrinfo
*, struct addrinfo
**);
7310 void (PASCAL
*pfn_freeaddrinfo
) (struct addrinfo
*);
7312 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7313 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7314 #ifndef HANDLE_FLAG_INHERIT
7315 #define HANDLE_FLAG_INHERIT 1
7319 static int winsock_inuse
;
7321 BOOL
term_winsock (void);
7326 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7328 release_listen_threads ();
7329 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7330 after WSAStartup returns successfully, but it seems reasonable
7331 to allow unloading winsock anyway in that case. */
7332 if (pfn_WSACleanup () == 0 ||
7333 pfn_WSAGetLastError () == WSAENETDOWN
)
7335 if (FreeLibrary (winsock_lib
))
7344 init_winsock (int load_now
)
7346 WSADATA winsockData
;
7348 if (winsock_lib
!= NULL
)
7351 pfn_SetHandleInformation
7352 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7353 "SetHandleInformation");
7355 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7357 if (winsock_lib
!= NULL
)
7359 /* dynamically link to socket functions */
7361 #define LOAD_PROC(fn) \
7362 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7365 LOAD_PROC (WSAStartup
);
7366 LOAD_PROC (WSASetLastError
);
7367 LOAD_PROC (WSAGetLastError
);
7368 LOAD_PROC (WSAEventSelect
);
7369 LOAD_PROC (WSAEnumNetworkEvents
);
7370 LOAD_PROC (WSACreateEvent
);
7371 LOAD_PROC (WSACloseEvent
);
7374 LOAD_PROC (connect
);
7375 LOAD_PROC (ioctlsocket
);
7378 LOAD_PROC (closesocket
);
7379 LOAD_PROC (shutdown
);
7382 LOAD_PROC (inet_addr
);
7383 LOAD_PROC (gethostname
);
7384 LOAD_PROC (gethostbyname
);
7385 LOAD_PROC (getservbyname
);
7386 LOAD_PROC (getpeername
);
7387 LOAD_PROC (WSACleanup
);
7388 LOAD_PROC (setsockopt
);
7390 LOAD_PROC (getsockname
);
7392 LOAD_PROC (recvfrom
);
7396 /* Try loading functions not available before XP. */
7397 pfn_getaddrinfo
= (void *) GetProcAddress (winsock_lib
, "getaddrinfo");
7398 pfn_freeaddrinfo
= (void *) GetProcAddress (winsock_lib
, "freeaddrinfo");
7399 /* Paranoia: these two functions should go together, so if one
7400 is absent, we cannot use the other. */
7401 if (pfn_getaddrinfo
== NULL
)
7402 pfn_freeaddrinfo
= NULL
;
7403 else if (pfn_freeaddrinfo
== NULL
)
7404 pfn_getaddrinfo
= NULL
;
7406 /* specify version 1.1 of winsock */
7407 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7409 if (winsockData
.wVersion
!= 0x101)
7414 /* Report that winsock exists and is usable, but leave
7415 socket functions disabled. I am assuming that calling
7416 WSAStartup does not require any network interaction,
7417 and in particular does not cause or require a dial-up
7418 connection to be established. */
7421 FreeLibrary (winsock_lib
);
7429 FreeLibrary (winsock_lib
);
7439 /* Function to map winsock error codes to errno codes for those errno
7440 code defined in errno.h (errno values not defined by errno.h are
7441 already in nt/inc/sys/socket.h). */
7448 if (winsock_lib
== NULL
)
7451 wsa_err
= pfn_WSAGetLastError ();
7455 case WSAEACCES
: errno
= EACCES
; break;
7456 case WSAEBADF
: errno
= EBADF
; break;
7457 case WSAEFAULT
: errno
= EFAULT
; break;
7458 case WSAEINTR
: errno
= EINTR
; break;
7459 case WSAEINVAL
: errno
= EINVAL
; break;
7460 case WSAEMFILE
: errno
= EMFILE
; break;
7461 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7462 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7463 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7464 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7465 default: errno
= wsa_err
; break;
7473 if (winsock_lib
!= NULL
)
7474 pfn_WSASetLastError (0);
7477 /* Extend strerror to handle the winsock-specific error codes. */
7481 } _wsa_errlist
[] = {
7482 {WSAEINTR
, "Interrupted function call"},
7483 {WSAEBADF
, "Bad file descriptor"},
7484 {WSAEACCES
, "Permission denied"},
7485 {WSAEFAULT
, "Bad address"},
7486 {WSAEINVAL
, "Invalid argument"},
7487 {WSAEMFILE
, "Too many open files"},
7489 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7490 {WSAEINPROGRESS
, "Operation now in progress"},
7491 {WSAEALREADY
, "Operation already in progress"},
7492 {WSAENOTSOCK
, "Socket operation on non-socket"},
7493 {WSAEDESTADDRREQ
, "Destination address required"},
7494 {WSAEMSGSIZE
, "Message too long"},
7495 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7496 {WSAENOPROTOOPT
, "Bad protocol option"},
7497 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7498 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7499 {WSAEOPNOTSUPP
, "Operation not supported"},
7500 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7501 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7502 {WSAEADDRINUSE
, "Address already in use"},
7503 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7504 {WSAENETDOWN
, "Network is down"},
7505 {WSAENETUNREACH
, "Network is unreachable"},
7506 {WSAENETRESET
, "Network dropped connection on reset"},
7507 {WSAECONNABORTED
, "Software caused connection abort"},
7508 {WSAECONNRESET
, "Connection reset by peer"},
7509 {WSAENOBUFS
, "No buffer space available"},
7510 {WSAEISCONN
, "Socket is already connected"},
7511 {WSAENOTCONN
, "Socket is not connected"},
7512 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7513 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7514 {WSAETIMEDOUT
, "Connection timed out"},
7515 {WSAECONNREFUSED
, "Connection refused"},
7516 {WSAELOOP
, "Network loop"}, /* not sure */
7517 {WSAENAMETOOLONG
, "Name is too long"},
7518 {WSAEHOSTDOWN
, "Host is down"},
7519 {WSAEHOSTUNREACH
, "No route to host"},
7520 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7521 {WSAEPROCLIM
, "Too many processes"},
7522 {WSAEUSERS
, "Too many users"}, /* not sure */
7523 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7524 {WSAESTALE
, "Data is stale"}, /* not sure */
7525 {WSAEREMOTE
, "Remote error"}, /* not sure */
7527 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7528 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7529 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7530 {WSAEDISCON
, "Graceful shutdown in progress"},
7532 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7533 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7534 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7535 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7536 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7537 {WSASYSCALLFAILURE
, "System call failure"},
7538 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7539 {WSATYPE_NOT_FOUND
, "Class type not found"},
7540 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7541 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7542 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7545 {WSAHOST_NOT_FOUND
, "Host not found"},
7546 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7547 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7548 {WSANO_DATA
, "Valid name, no data record of requested type"},
7554 sys_strerror (int error_no
)
7557 static char unknown_msg
[40];
7559 if (error_no
>= 0 && error_no
< sys_nerr
)
7560 return sys_errlist
[error_no
];
7562 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7563 if (_wsa_errlist
[i
].errnum
== error_no
)
7564 return (char *)_wsa_errlist
[i
].msg
;
7566 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7570 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7571 but I believe the method of keeping the socket handle separate (and
7572 insuring it is not inheritable) is the correct one. */
7574 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7576 static int socket_to_fd (SOCKET s
);
7579 sys_socket (int af
, int type
, int protocol
)
7583 if (winsock_lib
== NULL
)
7591 /* call the real socket function */
7592 s
= pfn_socket (af
, type
, protocol
);
7594 if (s
!= INVALID_SOCKET
)
7595 return socket_to_fd (s
);
7601 /* Convert a SOCKET to a file descriptor. */
7603 socket_to_fd (SOCKET s
)
7608 /* Although under NT 3.5 _open_osfhandle will accept a socket
7609 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7610 that does not work under NT 3.1. However, we can get the same
7611 effect by using a backdoor function to replace an existing
7612 descriptor handle with the one we want. */
7614 /* allocate a file descriptor (with appropriate flags) */
7615 fd
= _open ("NUL:", _O_RDWR
);
7618 /* Make a non-inheritable copy of the socket handle. Note
7619 that it is possible that sockets aren't actually kernel
7620 handles, which appears to be the case on Windows 9x when
7621 the MS Proxy winsock client is installed. */
7623 /* Apparently there is a bug in NT 3.51 with some service
7624 packs, which prevents using DuplicateHandle to make a
7625 socket handle non-inheritable (causes WSACleanup to
7626 hang). The work-around is to use SetHandleInformation
7627 instead if it is available and implemented. */
7628 if (pfn_SetHandleInformation
)
7630 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7634 HANDLE parent
= GetCurrentProcess ();
7635 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7637 if (DuplicateHandle (parent
,
7643 DUPLICATE_SAME_ACCESS
))
7645 /* It is possible that DuplicateHandle succeeds even
7646 though the socket wasn't really a kernel handle,
7647 because a real handle has the same value. So
7648 test whether the new handle really is a socket. */
7649 unsigned long nonblocking
= 0;
7650 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7652 pfn_closesocket (s
);
7657 CloseHandle (new_s
);
7662 eassert (fd
< MAXDESC
);
7663 fd_info
[fd
].hnd
= (HANDLE
) s
;
7665 /* set our own internal flags */
7666 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7672 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7674 /* attach child_process to fd_info */
7675 if (fd_info
[ fd
].cp
!= NULL
)
7677 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7681 fd_info
[ fd
].cp
= cp
;
7684 winsock_inuse
++; /* count open sockets */
7692 pfn_closesocket (s
);
7698 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7700 if (winsock_lib
== NULL
)
7703 return SOCKET_ERROR
;
7707 if (fd_info
[s
].flags
& FILE_SOCKET
)
7709 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7710 if (rc
== SOCKET_ERROR
)
7715 return SOCKET_ERROR
;
7719 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7721 if (winsock_lib
== NULL
)
7724 return SOCKET_ERROR
;
7728 if (fd_info
[s
].flags
& FILE_SOCKET
)
7730 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7731 if (rc
== SOCKET_ERROR
)
7734 /* If this is a non-blocking 'connect', set the bit in flags
7735 that will tell reader_thread to wait for connection
7736 before trying to read. */
7737 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7739 errno
= EINPROGRESS
; /* that's what process.c expects */
7740 fd_info
[s
].flags
|= FILE_CONNECT
;
7746 return SOCKET_ERROR
;
7750 sys_htons (u_short hostshort
)
7752 return (winsock_lib
!= NULL
) ?
7753 pfn_htons (hostshort
) : hostshort
;
7757 sys_ntohs (u_short netshort
)
7759 return (winsock_lib
!= NULL
) ?
7760 pfn_ntohs (netshort
) : netshort
;
7764 sys_inet_addr (const char * cp
)
7766 return (winsock_lib
!= NULL
) ?
7767 pfn_inet_addr (cp
) : INADDR_NONE
;
7771 sys_gethostname (char * name
, int namelen
)
7773 if (winsock_lib
!= NULL
)
7778 retval
= pfn_gethostname (name
, namelen
);
7779 if (retval
== SOCKET_ERROR
)
7784 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7785 return !GetComputerName (name
, (DWORD
*)&namelen
);
7788 return SOCKET_ERROR
;
7792 sys_gethostbyname (const char * name
)
7794 struct hostent
* host
;
7795 int h_err
= h_errno
;
7797 if (winsock_lib
== NULL
)
7799 h_errno
= NO_RECOVERY
;
7805 host
= pfn_gethostbyname (name
);
7817 sys_getservbyname (const char * name
, const char * proto
)
7819 struct servent
* serv
;
7821 if (winsock_lib
== NULL
)
7828 serv
= pfn_getservbyname (name
, proto
);
7835 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7837 if (winsock_lib
== NULL
)
7840 return SOCKET_ERROR
;
7844 if (fd_info
[s
].flags
& FILE_SOCKET
)
7846 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7847 if (rc
== SOCKET_ERROR
)
7852 return SOCKET_ERROR
;
7856 sys_getaddrinfo (const char *node
, const char *service
,
7857 const struct addrinfo
*hints
, struct addrinfo
**res
)
7861 if (winsock_lib
== NULL
)
7864 return SOCKET_ERROR
;
7868 if (pfn_getaddrinfo
)
7869 rc
= pfn_getaddrinfo (node
, service
, hints
, res
);
7873 struct hostent
*host_info
;
7874 struct gai_storage
{
7875 struct addrinfo addrinfo
;
7876 struct sockaddr_in sockaddr_in
;
7879 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7880 if (hints
&& hints
->ai_flags
!= 0)
7882 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7884 return WSAHOST_NOT_FOUND
;
7888 const char *protocol
=
7889 (hints
&& hints
->ai_socktype
== SOCK_DGRAM
) ? "udp" : "tcp";
7890 struct servent
*srv
= sys_getservbyname (service
, protocol
);
7894 else if (*service
>= '0' && *service
<= '9')
7898 port
= strtoul (service
, &endp
, 10);
7899 if (*endp
|| port
> 65536)
7900 return WSAHOST_NOT_FOUND
;
7901 port
= sys_htons ((unsigned short) port
);
7904 return WSAHOST_NOT_FOUND
;
7907 gai_storage
= xzalloc (sizeof *gai_storage
);
7908 gai_storage
->sockaddr_in
.sin_port
= port
;
7909 host_info
= sys_gethostbyname (node
);
7912 memcpy (&gai_storage
->sockaddr_in
.sin_addr
,
7913 host_info
->h_addr
, host_info
->h_length
);
7914 gai_storage
->sockaddr_in
.sin_family
= host_info
->h_addrtype
;
7918 /* Attempt to interpret host as numeric inet address. */
7919 unsigned long numeric_addr
= sys_inet_addr (node
);
7921 if (numeric_addr
== -1)
7924 return WSAHOST_NOT_FOUND
;
7927 memcpy (&gai_storage
->sockaddr_in
.sin_addr
, &numeric_addr
,
7928 sizeof (gai_storage
->sockaddr_in
.sin_addr
));
7929 gai_storage
->sockaddr_in
.sin_family
= (hints
) ? hints
->ai_family
: 0;
7932 gai_storage
->addrinfo
.ai_addr
=
7933 (struct sockaddr
*)&gai_storage
->sockaddr_in
;
7934 gai_storage
->addrinfo
.ai_addrlen
= sizeof (gai_storage
->sockaddr_in
);
7935 gai_storage
->addrinfo
.ai_protocol
= (hints
) ? hints
->ai_protocol
: 0;
7936 gai_storage
->addrinfo
.ai_socktype
= (hints
) ? hints
->ai_socktype
: 0;
7937 gai_storage
->addrinfo
.ai_family
= gai_storage
->sockaddr_in
.sin_family
;
7938 gai_storage
->addrinfo
.ai_next
= NULL
;
7940 *res
= &gai_storage
->addrinfo
;
7948 sys_freeaddrinfo (struct addrinfo
*ai
)
7950 if (winsock_lib
== NULL
)
7957 if (pfn_freeaddrinfo
)
7958 pfn_freeaddrinfo (ai
);
7961 eassert (ai
->ai_next
== NULL
);
7967 sys_shutdown (int s
, int how
)
7969 if (winsock_lib
== NULL
)
7972 return SOCKET_ERROR
;
7976 if (fd_info
[s
].flags
& FILE_SOCKET
)
7978 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7979 if (rc
== SOCKET_ERROR
)
7984 return SOCKET_ERROR
;
7988 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7990 if (winsock_lib
== NULL
)
7993 return SOCKET_ERROR
;
7997 if (fd_info
[s
].flags
& FILE_SOCKET
)
7999 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
8000 (const char *)optval
, optlen
);
8001 if (rc
== SOCKET_ERROR
)
8006 return SOCKET_ERROR
;
8010 sys_listen (int s
, int backlog
)
8012 if (winsock_lib
== NULL
)
8015 return SOCKET_ERROR
;
8019 if (fd_info
[s
].flags
& FILE_SOCKET
)
8021 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
8022 if (rc
== SOCKET_ERROR
)
8025 fd_info
[s
].flags
|= FILE_LISTEN
;
8029 return SOCKET_ERROR
;
8033 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
8035 if (winsock_lib
== NULL
)
8038 return SOCKET_ERROR
;
8042 if (fd_info
[s
].flags
& FILE_SOCKET
)
8044 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
8045 if (rc
== SOCKET_ERROR
)
8050 return SOCKET_ERROR
;
8054 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
8056 if (winsock_lib
== NULL
)
8063 if (fd_info
[s
].flags
& FILE_LISTEN
)
8065 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
8067 if (t
== INVALID_SOCKET
)
8070 fd
= socket_to_fd (t
);
8074 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8075 ResetEvent (fd_info
[s
].cp
->char_avail
);
8084 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
8085 struct sockaddr
* from
, int * fromlen
)
8087 if (winsock_lib
== NULL
)
8090 return SOCKET_ERROR
;
8094 if (fd_info
[s
].flags
& FILE_SOCKET
)
8096 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
8097 if (rc
== SOCKET_ERROR
)
8102 return SOCKET_ERROR
;
8106 sys_sendto (int s
, const char * buf
, int len
, int flags
,
8107 const struct sockaddr
* to
, int tolen
)
8109 if (winsock_lib
== NULL
)
8112 return SOCKET_ERROR
;
8116 if (fd_info
[s
].flags
& FILE_SOCKET
)
8118 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
8119 if (rc
== SOCKET_ERROR
)
8124 return SOCKET_ERROR
;
8127 /* Windows does not have an fcntl function. Provide an implementation
8128 good enough for Emacs. */
8130 fcntl (int s
, int cmd
, int options
)
8132 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8133 invoked in a context where fd1 is closed and all descriptors less
8134 than fd1 are open, so sys_dup is an adequate implementation. */
8135 if (cmd
== F_DUPFD_CLOEXEC
)
8139 if (fd_info
[s
].flags
& FILE_SOCKET
)
8141 if (winsock_lib
== NULL
)
8147 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8149 unsigned long nblock
= 1;
8150 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
8151 if (rc
== SOCKET_ERROR
)
8153 /* Keep track of the fact that we set this to non-blocking. */
8154 fd_info
[s
].flags
|= FILE_NDELAY
;
8160 return SOCKET_ERROR
;
8163 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
8164 == (FILE_PIPE
| FILE_WRITE
))
8166 /* Force our writes to pipes be non-blocking. */
8167 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8169 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
8170 DWORD pipe_mode
= PIPE_NOWAIT
;
8172 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
8174 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8175 return SOCKET_ERROR
;
8177 fd_info
[s
].flags
|= FILE_NDELAY
;
8183 return SOCKET_ERROR
;
8187 return SOCKET_ERROR
;
8191 /* Shadow main io functions: we need to handle pipes and sockets more
8205 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
8207 child_process
* cp
= fd_info
[fd
].cp
;
8209 fd_info
[fd
].cp
= NULL
;
8211 if (CHILD_ACTIVE (cp
))
8213 /* if last descriptor to active child_process then cleanup */
8215 for (i
= 0; i
< MAXDESC
; i
++)
8219 if (fd_info
[i
].cp
== cp
)
8224 if (fd_info
[fd
].flags
& FILE_SOCKET
)
8226 if (winsock_lib
== NULL
) emacs_abort ();
8228 pfn_shutdown (SOCK_HANDLE (fd
), 2);
8229 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
8231 winsock_inuse
--; /* count open sockets */
8233 /* If the process handle is NULL, it's either a socket
8234 or serial connection, or a subprocess that was
8235 already reaped by reap_subprocess, but whose
8236 resources were not yet freed, because its output was
8237 not fully read yet by the time it was reaped. (This
8238 usually happens with async subprocesses whose output
8239 is being read by Emacs.) Otherwise, this process was
8240 not reaped yet, so we set its FD to a negative value
8241 to make sure sys_select will eventually get to
8242 calling the SIGCHLD handler for it, which will then
8243 invoke waitpid and reap_subprocess. */
8244 if (cp
->procinfo
.hProcess
== NULL
)
8252 if (fd
>= 0 && fd
< MAXDESC
)
8253 fd_info
[fd
].flags
= 0;
8255 /* Note that sockets do not need special treatment here (at least on
8256 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8257 closesocket is equivalent to CloseHandle, which is to be expected
8258 because socket handles are fully fledged kernel handles. */
8270 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8272 /* duplicate our internal info as well */
8273 fd_info
[new_fd
] = fd_info
[fd
];
8279 sys_dup2 (int src
, int dst
)
8283 if (dst
< 0 || dst
>= MAXDESC
)
8289 /* MS _dup2 seems to have weird side effect when invoked with 2
8290 identical arguments: an attempt to fclose the corresponding stdio
8291 stream after that hangs (we do close standard streams in
8292 init_ntproc). Attempt to avoid that by not calling _dup2 that
8293 way: if SRC is valid, we know that dup2 should be a no-op, so do
8294 nothing and return DST. */
8297 if ((HANDLE
)_get_osfhandle (src
) == INVALID_HANDLE_VALUE
)
8305 /* Make sure we close the destination first if it's a pipe or socket. */
8306 if (fd_info
[dst
].flags
!= 0)
8309 rc
= _dup2 (src
, dst
);
8312 /* Duplicate our internal info as well. */
8313 fd_info
[dst
] = fd_info
[src
];
8315 return rc
== 0 ? dst
: rc
;
8319 pipe2 (int * phandles
, int pipe2_flags
)
8323 unsigned pipe_size
= 0;
8325 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8327 /* Allow Lisp to override the default buffer size of the pipe. */
8328 if (w32_pipe_buffer_size
> 0 && w32_pipe_buffer_size
< UINT_MAX
)
8329 pipe_size
= w32_pipe_buffer_size
;
8331 /* make pipe handles non-inheritable; when we spawn a child, we
8332 replace the relevant handle with an inheritable one. Also put
8333 pipes into binary mode; we will do text mode translation ourselves
8335 rc
= _pipe (phandles
, pipe_size
, _O_NOINHERIT
| _O_BINARY
);
8339 /* Protect against overflow, since Windows can open more handles than
8340 our fd_info array has room for. */
8341 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8343 _close (phandles
[0]);
8344 _close (phandles
[1]);
8350 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8351 fd_info
[phandles
[0]].flags
= flags
;
8353 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8354 fd_info
[phandles
[1]].flags
= flags
;
8361 /* Function to do blocking read of one byte, needed to implement
8362 select. It is only allowed on communication ports, sockets, or
8365 _sys_read_ahead (int fd
)
8370 if (fd
< 0 || fd
>= MAXDESC
)
8371 return STATUS_READ_ERROR
;
8373 cp
= fd_info
[fd
].cp
;
8375 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8376 return STATUS_READ_ERROR
;
8378 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8379 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8381 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8385 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8386 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8387 cp
->status
= STATUS_READ_IN_PROGRESS
;
8389 if (fd_info
[fd
].flags
& FILE_PIPE
)
8391 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8393 /* Give subprocess time to buffer some more output for us before
8394 reporting that input is available; we need this because Windows 95
8395 connects DOS programs to pipes by making the pipe appear to be
8396 the normal console stdout - as a result most DOS programs will
8397 write to stdout without buffering, ie. one character at a
8398 time. Even some W32 programs do this - "dir" in a command
8399 shell on NT is very slow if we don't do this. */
8402 int wait
= w32_pipe_read_delay
;
8408 /* Yield remainder of our time slice, effectively giving a
8409 temporary priority boost to the child process. */
8413 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8415 HANDLE hnd
= fd_info
[fd
].hnd
;
8416 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8419 /* Configure timeouts for blocking read. */
8420 if (!GetCommTimeouts (hnd
, &ct
))
8422 cp
->status
= STATUS_READ_ERROR
;
8423 return STATUS_READ_ERROR
;
8425 ct
.ReadIntervalTimeout
= 0;
8426 ct
.ReadTotalTimeoutMultiplier
= 0;
8427 ct
.ReadTotalTimeoutConstant
= 0;
8428 if (!SetCommTimeouts (hnd
, &ct
))
8430 cp
->status
= STATUS_READ_ERROR
;
8431 return STATUS_READ_ERROR
;
8434 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8436 if (GetLastError () != ERROR_IO_PENDING
)
8438 cp
->status
= STATUS_READ_ERROR
;
8439 return STATUS_READ_ERROR
;
8441 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8443 cp
->status
= STATUS_READ_ERROR
;
8444 return STATUS_READ_ERROR
;
8448 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8450 unsigned long nblock
= 0;
8451 /* We always want this to block, so temporarily disable NDELAY. */
8452 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8453 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8455 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8457 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8460 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8464 if (rc
== sizeof (char))
8465 cp
->status
= STATUS_READ_SUCCEEDED
;
8467 cp
->status
= STATUS_READ_FAILED
;
8473 _sys_wait_accept (int fd
)
8479 if (fd
< 0 || fd
>= MAXDESC
)
8480 return STATUS_READ_ERROR
;
8482 cp
= fd_info
[fd
].cp
;
8484 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8485 return STATUS_READ_ERROR
;
8487 cp
->status
= STATUS_READ_FAILED
;
8489 hEv
= pfn_WSACreateEvent ();
8490 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8491 if (rc
!= SOCKET_ERROR
)
8494 rc
= WaitForSingleObject (hEv
, 500);
8496 } while (rc
== WAIT_TIMEOUT
8497 && cp
->status
!= STATUS_READ_ERROR
8499 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8500 if (rc
== WAIT_OBJECT_0
)
8501 cp
->status
= STATUS_READ_SUCCEEDED
;
8503 pfn_WSACloseEvent (hEv
);
8509 _sys_wait_connect (int fd
)
8515 if (fd
< 0 || fd
>= MAXDESC
)
8516 return STATUS_READ_ERROR
;
8518 cp
= fd_info
[fd
].cp
;
8519 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8520 return STATUS_READ_ERROR
;
8522 cp
->status
= STATUS_READ_FAILED
;
8524 hEv
= pfn_WSACreateEvent ();
8525 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8526 if (rc
!= SOCKET_ERROR
)
8529 rc
= WaitForSingleObject (hEv
, 500);
8531 } while (rc
== WAIT_TIMEOUT
8532 && cp
->status
!= STATUS_READ_ERROR
8534 if (rc
== WAIT_OBJECT_0
)
8536 /* We've got an event, but it could be a successful
8537 connection, or it could be a failure. Find out
8539 WSANETWORKEVENTS events
;
8541 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8542 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8543 && events
.iErrorCode
[FD_CONNECT_BIT
])
8545 cp
->status
= STATUS_CONNECT_FAILED
;
8546 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8550 cp
->status
= STATUS_READ_SUCCEEDED
;
8554 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8557 pfn_WSACloseEvent (hEv
);
8563 sys_read (int fd
, char * buffer
, unsigned int count
)
8568 char * orig_buffer
= buffer
;
8576 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8578 child_process
*cp
= fd_info
[fd
].cp
;
8580 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8588 /* re-read CR carried over from last read */
8589 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8591 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8595 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8598 /* presence of a child_process structure means we are operating in
8599 non-blocking mode - otherwise we just call _read directly.
8600 Note that the child_process structure might be missing because
8601 reap_subprocess has been called; in this case the pipe is
8602 already broken, so calling _read on it is okay. */
8605 int current_status
= cp
->status
;
8607 switch (current_status
)
8609 case STATUS_READ_FAILED
:
8610 case STATUS_READ_ERROR
:
8611 /* report normal EOF if nothing in buffer */
8613 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8616 case STATUS_READ_READY
:
8617 case STATUS_READ_IN_PROGRESS
:
8619 /* This happens all the time during GnuTLS handshake
8620 with the remote, evidently because GnuTLS waits for
8621 the read to complete by retrying the read operation
8622 upon EAGAIN. So I'm disabling the DebPrint to avoid
8623 wasting cycles on something that is not a real
8624 problem. Enable if you need to debug something that
8626 DebPrint (("sys_read called when read is in progress %d\n",
8629 errno
= EWOULDBLOCK
;
8632 case STATUS_READ_SUCCEEDED
:
8633 /* consume read-ahead char */
8634 *buffer
++ = cp
->chr
;
8637 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8638 ResetEvent (cp
->char_avail
);
8640 case STATUS_READ_ACKNOWLEDGED
:
8641 case STATUS_CONNECT_FAILED
:
8645 DebPrint (("sys_read: bad status %d\n", current_status
));
8650 if (fd_info
[fd
].flags
& FILE_PIPE
)
8652 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8653 to_read
= min (waiting
, (DWORD
) count
);
8656 nchars
+= _read (fd
, buffer
, to_read
);
8658 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8660 HANDLE hnd
= fd_info
[fd
].hnd
;
8661 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8667 /* Configure timeouts for non-blocking read. */
8668 if (!GetCommTimeouts (hnd
, &ct
))
8673 ct
.ReadIntervalTimeout
= MAXDWORD
;
8674 ct
.ReadTotalTimeoutMultiplier
= 0;
8675 ct
.ReadTotalTimeoutConstant
= 0;
8676 if (!SetCommTimeouts (hnd
, &ct
))
8682 if (!ResetEvent (ovl
->hEvent
))
8687 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8689 if (GetLastError () != ERROR_IO_PENDING
)
8694 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8703 else /* FILE_SOCKET */
8705 if (winsock_lib
== NULL
) emacs_abort ();
8707 /* When a non-blocking 'connect' call fails,
8708 wait_reading_process_output detects this by calling
8709 'getpeername', and then attempts to obtain the connection
8710 error code by trying to read 1 byte from the socket. If
8711 we try to serve that read by calling 'recv' below, the
8712 error we get is a generic WSAENOTCONN, not the actual
8713 connection error. So instead, we use the actual error
8714 code stashed by '_sys_wait_connect' in cp->errcode.
8715 Alternatively, we could have used 'getsockopt', like on
8716 GNU/Linux, but: (a) I have no idea whether the winsock
8717 version could hang, as it does "on some systems" (see the
8718 comment in process.c); and (b) 'getsockopt' on Windows is
8719 documented to clear the socket error for the entire
8720 process, which I'm not sure is TRT; FIXME. */
8721 if (current_status
== STATUS_CONNECT_FAILED
8722 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8723 && cp
->errcode
!= 0)
8725 pfn_WSASetLastError (cp
->errcode
);
8729 /* Do the equivalent of a non-blocking read. */
8730 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8731 if (waiting
== 0 && nchars
== 0)
8733 errno
= EWOULDBLOCK
;
8739 /* always use binary mode for sockets */
8740 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8741 if (res
== SOCKET_ERROR
)
8744 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8745 errno
, SOCK_HANDLE (fd
)));
8754 int nread
= _read (fd
, buffer
, count
);
8757 else if (nchars
== 0)
8762 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8763 /* Perform text mode translation if required. */
8764 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8766 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8767 /* If buffer contains only CR, return that. To be absolutely
8768 sure we should attempt to read the next char, but in
8769 practice a CR to be followed by LF would not appear by
8770 itself in the buffer. */
8771 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8773 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8779 nchars
= _read (fd
, buffer
, count
);
8784 /* From w32xfns.c */
8785 extern HANDLE interrupt_handle
;
8788 sys_write (int fd
, const void * buffer
, unsigned int count
)
8799 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8801 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8807 /* Perform text mode translation if required. */
8808 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8811 const unsigned char * src
= buffer
;
8812 unsigned char * dst
;
8815 SAFE_NALLOCA (tmpbuf
, 2, count
);
8816 dst
= (unsigned char *)tmpbuf
;
8820 unsigned char *next
;
8821 /* Copy next line or remaining bytes. */
8822 next
= _memccpy (dst
, src
, '\n', nbytes
);
8825 /* Copied one line ending with '\n'. */
8826 int copied
= next
- dst
;
8829 /* Insert '\r' before '\n'. */
8836 /* Copied remaining partial line -> now finished. */
8843 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8845 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8846 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8847 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8850 /* This is async (a.k.a. "overlapped") I/O, so the return value
8851 of FALSE from WriteFile means either an error or the output
8852 will be completed asynchronously (ERROR_IO_PENDING). */
8853 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8855 if (GetLastError () != ERROR_IO_PENDING
)
8862 /* Wait for the write to complete, and watch C-g while
8864 if (detect_input_pending ())
8865 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8866 INFINITE
, QS_ALLINPUT
);
8868 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8872 /* User pressed C-g, cancel write, then leave.
8873 Don't bother cleaning up as we may only get stuck
8874 in buggy drivers. */
8875 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8877 errno
= EIO
; /* Why not EINTR? */
8880 case WAIT_OBJECT_0
+ 1:
8881 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8891 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8893 unsigned long nblock
= 0;
8894 if (winsock_lib
== NULL
) emacs_abort ();
8896 child_process
*cp
= fd_info
[fd
].cp
;
8898 /* If this is a non-blocking socket whose connection is in
8899 progress or terminated with an error already, return the
8900 proper error code to the caller. */
8901 if (cp
!= NULL
&& (fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8903 /* In case connection is in progress, ENOTCONN that would
8904 result from calling pfn_send is not what callers expect. */
8905 if (cp
->status
!= STATUS_CONNECT_FAILED
)
8907 errno
= EWOULDBLOCK
;
8910 /* In case connection failed, use the actual error code
8911 stashed by '_sys_wait_connect' in cp->errcode. */
8912 else if (cp
->errcode
!= 0)
8914 pfn_WSASetLastError (cp
->errcode
);
8920 /* TODO: implement select() properly so non-blocking I/O works. */
8921 /* For now, make sure the write blocks. */
8922 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8923 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8925 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8927 if (nchars
== SOCKET_ERROR
)
8930 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8931 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8934 /* Set the socket back to non-blocking if it was before,
8935 for other operations that support it. */
8936 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8939 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8944 /* Some networked filesystems don't like too large writes, so
8945 break them into smaller chunks. See the Comments section of
8946 the MSDN documentation of WriteFile for details behind the
8947 choice of the value of CHUNK below. See also the thread
8948 http://thread.gmane.org/gmane.comp.version-control.git/145294
8949 in the git mailing list. */
8950 const unsigned char *p
= buffer
;
8951 const bool is_pipe
= (fd
< MAXDESC
8952 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8953 == (FILE_PIPE
| FILE_NDELAY
)));
8954 /* Some programs, notably Node.js's node.exe, seem to never
8955 completely empty the pipe, so writing more than the size of
8956 the pipe's buffer always returns ENOSPC, and we loop forever
8957 between send_process and here. As a workaround, write no
8958 more than the pipe's buffer can hold. */
8959 DWORD pipe_buffer_size
;
8962 if (!GetNamedPipeInfo ((HANDLE
)_get_osfhandle (fd
),
8963 NULL
, &pipe_buffer_size
, NULL
, NULL
))
8965 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8966 pipe_buffer_size
= 4096;
8969 const unsigned chunk
= is_pipe
? pipe_buffer_size
: 30 * 1024 * 1024;
8975 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8976 int n
= _write (fd
, p
, this_chunk
);
8982 /* When there's no buffer space in a pipe that is in the
8983 non-blocking mode, _write returns ENOSPC. We return
8984 EAGAIN instead, which should trigger the logic in
8985 send_process that enters waiting loop and calls
8986 wait_reading_process_output to allow process input to
8987 be accepted during the wait. Those calls to
8988 wait_reading_process_output allow sys_select to
8989 notice when process input becomes available, thus
8990 avoiding deadlock whereby each side of the pipe is
8991 blocked on write, waiting for the other party to read
8992 its end of the pipe. */
8993 if (errno
== ENOSPC
&& is_pipe
)
8999 else if (n
< this_chunk
)
9011 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
9013 /* Return information about network interface IFNAME, or about all
9014 interfaces (if IFNAME is nil). */
9016 network_interface_get_info (Lisp_Object ifname
)
9018 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
9019 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
9020 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
9021 Lisp_Object res
= Qnil
;
9023 if (retval
== ERROR_BUFFER_OVERFLOW
)
9025 ainfo
= xrealloc (ainfo
, ainfo_len
);
9026 retval
= get_adapters_info (ainfo
, &ainfo_len
);
9029 if (retval
== ERROR_SUCCESS
)
9031 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
9032 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
9034 struct sockaddr_in sa
;
9036 /* For the below, we need some winsock functions, so make sure
9037 the winsock DLL is loaded. If we cannot successfully load
9038 it, they will have no use of the information we provide,
9040 if (!winsock_lib
&& !init_winsock (1))
9043 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
9045 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
9047 /* Present Unix-compatible interface names, instead of the
9048 Windows names, which are really GUIDs not readable by
9050 static const char *ifmt
[] = {
9051 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9066 switch (adapter
->Type
)
9068 case MIB_IF_TYPE_ETHERNET
:
9069 /* Windows before Vista reports wireless adapters as
9070 Ethernet. Work around by looking at the Description
9072 if (strstr (adapter
->Description
, "Wireless "))
9075 if_num
= wlan_count
++;
9079 ifmt_idx
= ETHERNET
;
9080 if_num
= eth_count
++;
9083 case MIB_IF_TYPE_TOKENRING
:
9084 ifmt_idx
= TOKENRING
;
9085 if_num
= tr_count
++;
9087 case MIB_IF_TYPE_FDDI
:
9089 if_num
= fddi_count
++;
9091 case MIB_IF_TYPE_PPP
:
9093 if_num
= ppp_count
++;
9095 case MIB_IF_TYPE_SLIP
:
9097 if_num
= sl_count
++;
9099 case IF_TYPE_IEEE80211
:
9101 if_num
= wlan_count
++;
9103 case MIB_IF_TYPE_LOOPBACK
:
9106 ifmt_idx
= LOOPBACK
;
9107 if_num
= lo_count
++;
9113 ifmt_idx
= OTHER_IF
;
9114 if_num
= ifx_count
++;
9117 if (ifmt_idx
== NONE
)
9119 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
9121 sa
.sin_family
= AF_INET
;
9122 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
9123 if (ip_addr
== INADDR_NONE
)
9125 /* Bogus address, skip this interface. */
9128 sa
.sin_addr
.s_addr
= ip_addr
;
9131 res
= Fcons (Fcons (build_string (namebuf
),
9132 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9133 sizeof (struct sockaddr
))),
9135 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
9137 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
9138 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
9139 Lisp_Object flags
= Qnil
;
9143 /* Flags. We guess most of them by type, since the
9144 Windows flags are different and hard to get by. */
9145 flags
= Fcons (intern ("up"), flags
);
9146 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
9148 flags
= Fcons (intern ("broadcast"), flags
);
9149 flags
= Fcons (intern ("multicast"), flags
);
9151 flags
= Fcons (intern ("running"), flags
);
9152 if (ifmt_idx
== PPP
)
9154 flags
= Fcons (intern ("pointopoint"), flags
);
9155 flags
= Fcons (intern ("noarp"), flags
);
9157 if (adapter
->HaveWins
)
9158 flags
= Fcons (intern ("WINS"), flags
);
9159 if (adapter
->DhcpEnabled
)
9160 flags
= Fcons (intern ("dynamic"), flags
);
9162 res
= Fcons (flags
, res
);
9164 /* Hardware address and its family. */
9165 for (n
= 0; n
< adapter
->AddressLength
; n
++)
9166 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
9167 /* Windows does not support AF_LINK or AF_PACKET family
9168 of addresses. Use an arbitrary family number that is
9169 identical to what GNU/Linux returns. */
9170 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
9173 sa
.sin_family
= AF_INET
;
9174 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
9175 if (net_mask
!= INADDR_NONE
)
9177 sa
.sin_addr
.s_addr
= net_mask
;
9179 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9180 sizeof (struct sockaddr
)),
9184 res
= Fcons (Qnil
, res
);
9186 sa
.sin_family
= AF_INET
;
9187 if (ip_addr
!= INADDR_NONE
)
9189 /* Broadcast address is only reported by
9190 GetAdaptersAddresses, which is of limited
9191 availability. Generate it on our own. */
9192 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
9194 sa
.sin_addr
.s_addr
= bcast_addr
;
9196 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9197 sizeof (struct sockaddr
)),
9201 sa
.sin_addr
.s_addr
= ip_addr
;
9203 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9204 sizeof (struct sockaddr
)),
9208 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
9211 /* GetAdaptersInfo is documented to not report loopback
9212 interfaces, so we generate one out of thin air. */
9215 sa
.sin_family
= AF_INET
;
9219 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9220 res
= Fcons (Fcons (build_string ("lo"),
9221 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9222 sizeof (struct sockaddr
))),
9225 else if (strcmp (SSDATA (ifname
), "lo") == 0)
9227 res
= Fcons (Fcons (intern ("running"),
9228 Fcons (intern ("loopback"),
9229 Fcons (intern ("up"), Qnil
))), Qnil
);
9230 /* 772 is what 3 different GNU/Linux systems report for
9231 the loopback interface. */
9232 res
= Fcons (Fcons (make_number (772),
9233 Fmake_vector (make_number (6),
9236 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
9237 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9238 sizeof (struct sockaddr
)),
9240 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
9241 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9242 sizeof (struct sockaddr
)),
9244 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9245 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9246 sizeof (struct sockaddr
)),
9259 network_interface_list (void)
9261 return network_interface_get_info (Qnil
);
9265 network_interface_info (Lisp_Object ifname
)
9267 CHECK_STRING (ifname
);
9268 return network_interface_get_info (ifname
);
9272 /* The Windows CRT functions are "optimized for speed", so they don't
9273 check for timezone and DST changes if they were last called less
9274 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9275 all Emacs features that repeatedly call time functions (e.g.,
9276 display-time) are in real danger of missing timezone and DST
9277 changes. Calling tzset before each localtime call fixes that. */
9279 sys_localtime (const time_t *t
)
9282 return localtime (t
);
9287 /* Try loading LIBRARY_ID from the file(s) specified in
9288 Vdynamic_library_alist. If the library is loaded successfully,
9289 return the handle of the DLL, and record the filename in the
9290 property :loaded-from of LIBRARY_ID. If the library could not be
9291 found, or when it was already loaded (because the handle is not
9292 recorded anywhere, and so is lost after use), return NULL.
9294 We could also save the handle in :loaded-from, but currently
9295 there's no use case for it. */
9297 w32_delayed_load (Lisp_Object library_id
)
9299 HMODULE dll_handle
= NULL
;
9301 CHECK_SYMBOL (library_id
);
9303 if (CONSP (Vdynamic_library_alist
)
9304 && NILP (Fassq (library_id
, Vlibrary_cache
)))
9306 Lisp_Object found
= Qnil
;
9307 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
9310 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
9312 Lisp_Object dll
= XCAR (dlls
);
9313 char name
[MAX_UTF8_PATH
];
9317 dll
= ENCODE_FILE (dll
);
9318 if (w32_unicode_filenames
)
9320 wchar_t name_w
[MAX_PATH
];
9322 filename_to_utf16 (SSDATA (dll
), name_w
);
9323 dll_handle
= LoadLibraryW (name_w
);
9326 res
= GetModuleFileNameW (dll_handle
, name_w
,
9329 filename_from_utf16 (name_w
, name
);
9334 char name_a
[MAX_PATH
];
9336 filename_to_ansi (SSDATA (dll
), name_a
);
9337 dll_handle
= LoadLibraryA (name_a
);
9340 res
= GetModuleFileNameA (dll_handle
, name_a
,
9343 filename_from_ansi (name_a
, name
);
9348 ptrdiff_t len
= strlen (name
);
9351 /* Possibly truncated */
9352 ? make_specified_string (name
, -1, len
, 1)
9354 /* This prevents thread start and end notifications
9355 from being sent to the DLL, for every thread we
9356 start. We don't need those notifications because
9357 threads we create never use any of these DLLs, only
9358 the main thread uses them. This is supposed to
9359 speed up thread creation. */
9360 DisableThreadLibraryCalls (dll_handle
);
9365 Fput (library_id
, QCloaded_from
, found
);
9373 check_windows_init_file (void)
9375 /* A common indication that Emacs is not installed properly is when
9376 it cannot find the Windows installation file. If this file does
9377 not exist in the expected place, tell the user. */
9379 if (!noninteractive
&& !inhibit_window_system
9380 /* Vload_path is not yet initialized when we are loading
9382 && NILP (Vpurify_flag
))
9384 Lisp_Object init_file
;
9387 /* Implementation note: this function runs early during Emacs
9388 startup, before startup.el is run. So Vload_path is still in
9389 its initial unibyte form, but it holds UTF-8 encoded file
9390 names, since init_callproc was already called. So we do not
9391 need to ENCODE_FILE here, but we do need to convert the file
9392 names from UTF-8 to ANSI. */
9393 init_file
= build_string ("term/w32-win");
9394 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9397 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9398 char *init_file_name
= SSDATA (init_file
);
9399 char *load_path
= SSDATA (load_path_print
);
9400 char *buffer
= alloca (1024
9401 + strlen (init_file_name
)
9402 + strlen (load_path
));
9407 "The Emacs Windows initialization file \"%s.el\" "
9408 "could not be found in your Emacs installation. "
9409 "Emacs checked the following directories for this file:\n"
9411 "When Emacs cannot find this file, it usually means that it "
9412 "was not installed properly, or its distribution file was "
9413 "not unpacked properly.\nSee the README.W32 file in the "
9414 "top-level Emacs directory for more information.",
9415 init_file_name
, load_path
);
9416 needed
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
,
9417 buffer
, -1, NULL
, 0);
9420 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9422 pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, buffer
,
9424 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9425 NULL
, 0, NULL
, NULL
);
9428 char *msg_a
= alloca (needed
+ 1);
9430 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9437 "Emacs Abort Dialog",
9438 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9439 /* Use the low-level system abort. */
9450 term_ntproc (int ignored
)
9456 /* shutdown the socket interface if necessary */
9463 init_ntproc (int dumping
)
9465 sigset_t initial_mask
= 0;
9467 /* Initialize the socket interface now if available and requested by
9468 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9469 delayed until open-network-stream is called (w32-has-winsock can
9470 also be used to dynamically load or reload winsock).
9472 Conveniently, init_environment is called before us, so
9473 PRELOAD_WINSOCK can be set in the registry. */
9475 /* Always initialize this correctly. */
9478 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9479 init_winsock (TRUE
);
9481 /* Initial preparation for subprocess support: replace our standard
9482 handles with non-inheritable versions. */
9485 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9486 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9487 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9489 parent
= GetCurrentProcess ();
9491 /* ignore errors when duplicating and closing; typically the
9492 handles will be invalid when running as a gui program. */
9493 DuplicateHandle (parent
,
9494 GetStdHandle (STD_INPUT_HANDLE
),
9499 DUPLICATE_SAME_ACCESS
);
9501 DuplicateHandle (parent
,
9502 GetStdHandle (STD_OUTPUT_HANDLE
),
9507 DUPLICATE_SAME_ACCESS
);
9509 DuplicateHandle (parent
,
9510 GetStdHandle (STD_ERROR_HANDLE
),
9515 DUPLICATE_SAME_ACCESS
);
9521 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9522 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9524 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9527 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9528 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9530 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9533 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9534 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9536 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9540 /* unfortunately, atexit depends on implementation of malloc */
9541 /* atexit (term_ntproc); */
9544 /* Make sure we start with all signals unblocked. */
9545 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9546 signal (SIGABRT
, term_ntproc
);
9550 /* determine which drives are fixed, for GetCachedVolumeInformation */
9552 /* GetDriveType must have trailing backslash. */
9553 char drive
[] = "A:\\";
9555 /* Loop over all possible drive letters */
9556 while (*drive
<= 'Z')
9558 /* Record if this drive letter refers to a fixed drive. */
9559 fixed_drives
[DRIVE_INDEX (*drive
)] =
9560 (GetDriveType (drive
) == DRIVE_FIXED
);
9565 /* Reset the volume info cache. */
9566 volume_cache
= NULL
;
9571 shutdown_handler ensures that buffers' autosave files are
9572 up to date when the user logs off, or the system shuts down.
9575 shutdown_handler (DWORD type
)
9577 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9578 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9579 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9580 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9582 /* Shut down cleanly, making sure autosave files are up to date. */
9583 shut_down_emacs (0, Qnil
);
9586 /* Allow other handlers to handle this signal. */
9590 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9591 NT, return a handle to GDI32.DLL. */
9593 maybe_load_unicows_dll (void)
9595 if (os_subtype
== OS_9X
)
9597 HANDLE ret
= LoadLibrary ("Unicows.dll");
9600 /* These two functions are present on Windows 9X as stubs
9601 that always fail. We need the real implementations from
9602 UNICOWS.DLL, so we must call these functions through
9603 pointers, and assign the correct addresses to these
9604 pointers at program startup (see emacs.c, which calls
9605 this function early on). */
9606 pMultiByteToWideChar
=
9607 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9608 pWideCharToMultiByte
=
9609 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9610 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9617 button
= MessageBox (NULL
,
9618 "Emacs cannot load the UNICOWS.DLL library.\n"
9619 "This library is essential for using Emacs\n"
9620 "on this system. You need to install it.\n\n"
9621 "Emacs will exit when you click OK.",
9622 "Emacs cannot load UNICOWS.DLL",
9623 MB_ICONERROR
| MB_TASKMODAL
9624 | MB_SETFOREGROUND
| MB_OK
);
9635 /* On NT family of Windows, these two functions are always
9636 linked in, so we just assign their addresses to the 2
9637 pointers; no need for the LoadLibrary dance. */
9638 pMultiByteToWideChar
= MultiByteToWideChar
;
9639 pWideCharToMultiByte
= WideCharToMultiByte
;
9640 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9641 if (w32_major_version
< 5)
9642 multiByteToWideCharFlags
= 0;
9644 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9645 return LoadLibrary ("Gdi32.dll");
9650 globals_of_w32 is used to initialize those global variables that
9651 must always be initialized on startup even when the global variable
9652 initialized is non zero (see the function main in emacs.c).
9655 globals_of_w32 (void)
9657 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9659 get_process_times_fn
= (GetProcessTimes_Proc
)
9660 GetProcAddress (kernel32
, "GetProcessTimes");
9662 DEFSYM (QCloaded_from
, ":loaded-from");
9664 g_b_init_is_windows_9x
= 0;
9665 g_b_init_open_process_token
= 0;
9666 g_b_init_get_token_information
= 0;
9667 g_b_init_lookup_account_sid
= 0;
9668 g_b_init_get_sid_sub_authority
= 0;
9669 g_b_init_get_sid_sub_authority_count
= 0;
9670 g_b_init_get_security_info
= 0;
9671 g_b_init_get_file_security_w
= 0;
9672 g_b_init_get_file_security_a
= 0;
9673 g_b_init_get_security_descriptor_owner
= 0;
9674 g_b_init_get_security_descriptor_group
= 0;
9675 g_b_init_is_valid_sid
= 0;
9676 g_b_init_create_toolhelp32_snapshot
= 0;
9677 g_b_init_process32_first
= 0;
9678 g_b_init_process32_next
= 0;
9679 g_b_init_open_thread_token
= 0;
9680 g_b_init_impersonate_self
= 0;
9681 g_b_init_revert_to_self
= 0;
9682 g_b_init_get_process_memory_info
= 0;
9683 g_b_init_get_process_working_set_size
= 0;
9684 g_b_init_global_memory_status
= 0;
9685 g_b_init_global_memory_status_ex
= 0;
9686 g_b_init_equal_sid
= 0;
9687 g_b_init_copy_sid
= 0;
9688 g_b_init_get_length_sid
= 0;
9689 g_b_init_get_native_system_info
= 0;
9690 g_b_init_get_system_times
= 0;
9691 g_b_init_create_symbolic_link_w
= 0;
9692 g_b_init_create_symbolic_link_a
= 0;
9693 g_b_init_get_security_descriptor_dacl
= 0;
9694 g_b_init_convert_sd_to_sddl
= 0;
9695 g_b_init_convert_sddl_to_sd
= 0;
9696 g_b_init_is_valid_security_descriptor
= 0;
9697 g_b_init_set_file_security_w
= 0;
9698 g_b_init_set_file_security_a
= 0;
9699 g_b_init_set_named_security_info_w
= 0;
9700 g_b_init_set_named_security_info_a
= 0;
9701 g_b_init_get_adapters_info
= 0;
9702 g_b_init_compare_string_w
= 0;
9703 g_b_init_debug_break_process
= 0;
9704 num_of_processors
= 0;
9705 /* The following sets a handler for shutdown notifications for
9706 console apps. This actually applies to Emacs in both console and
9707 GUI modes, since we had to fool windows into thinking emacs is a
9708 console application to get console mode to work. */
9709 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9711 /* "None" is the default group name on standalone workstations. */
9712 strcpy (dflt_group_name
, "None");
9714 /* Reset, in case it has some value inherited from dump time. */
9715 w32_stat_get_owner_group
= 0;
9717 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9718 (a.k.a. "wide") APIs to invoke functions that accept file
9720 if (is_windows_9x ())
9721 w32_unicode_filenames
= 0;
9723 w32_unicode_filenames
= 1;
9726 dynlib_reset_last_error ();
9729 w32_crypto_hprov
= (HCRYPTPROV
)0;
9732 /* For make-serial-process */
9734 serial_open (Lisp_Object port_obj
)
9736 char *port
= SSDATA (port_obj
);
9741 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9742 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9743 if (hnd
== INVALID_HANDLE_VALUE
)
9744 error ("Could not open %s", port
);
9745 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9747 error ("Could not open %s", port
);
9751 error ("Could not create child process");
9753 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9754 fd_info
[ fd
].hnd
= hnd
;
9755 fd_info
[ fd
].flags
|=
9756 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9757 if (fd_info
[ fd
].cp
!= NULL
)
9759 error ("fd_info[fd = %d] is already in use", fd
);
9761 fd_info
[ fd
].cp
= cp
;
9762 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9763 if (cp
->ovl_read
.hEvent
== NULL
)
9764 error ("Could not create read event");
9765 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9766 if (cp
->ovl_write
.hEvent
== NULL
)
9767 error ("Could not create write event");
9772 /* For serial-process-configure */
9774 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9776 Lisp_Object childp2
= Qnil
;
9777 Lisp_Object tem
= Qnil
;
9781 char summary
[4] = "???"; /* This usually becomes "8N1". */
9783 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9784 error ("Not a serial process");
9785 hnd
= fd_info
[ p
->outfd
].hnd
;
9787 childp2
= Fcopy_sequence (p
->childp
);
9789 /* Initialize timeouts for blocking read and blocking write. */
9790 if (!GetCommTimeouts (hnd
, &ct
))
9791 error ("GetCommTimeouts() failed");
9792 ct
.ReadIntervalTimeout
= 0;
9793 ct
.ReadTotalTimeoutMultiplier
= 0;
9794 ct
.ReadTotalTimeoutConstant
= 0;
9795 ct
.WriteTotalTimeoutMultiplier
= 0;
9796 ct
.WriteTotalTimeoutConstant
= 0;
9797 if (!SetCommTimeouts (hnd
, &ct
))
9798 error ("SetCommTimeouts() failed");
9799 /* Read port attributes and prepare default configuration. */
9800 memset (&dcb
, 0, sizeof (dcb
));
9801 dcb
.DCBlength
= sizeof (DCB
);
9802 if (!GetCommState (hnd
, &dcb
))
9803 error ("GetCommState() failed");
9806 dcb
.fAbortOnError
= FALSE
;
9807 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9812 /* Configure speed. */
9813 if (!NILP (Fplist_member (contact
, QCspeed
)))
9814 tem
= Fplist_get (contact
, QCspeed
);
9816 tem
= Fplist_get (p
->childp
, QCspeed
);
9818 dcb
.BaudRate
= XINT (tem
);
9819 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9821 /* Configure bytesize. */
9822 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9823 tem
= Fplist_get (contact
, QCbytesize
);
9825 tem
= Fplist_get (p
->childp
, QCbytesize
);
9827 tem
= make_number (8);
9829 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9830 error (":bytesize must be nil (8), 7, or 8");
9831 dcb
.ByteSize
= XINT (tem
);
9832 summary
[0] = XINT (tem
) + '0';
9833 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9835 /* Configure parity. */
9836 if (!NILP (Fplist_member (contact
, QCparity
)))
9837 tem
= Fplist_get (contact
, QCparity
);
9839 tem
= Fplist_get (p
->childp
, QCparity
);
9840 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9841 error (":parity must be nil (no parity), `even', or `odd'");
9842 dcb
.fParity
= FALSE
;
9843 dcb
.Parity
= NOPARITY
;
9844 dcb
.fErrorChar
= FALSE
;
9849 else if (EQ (tem
, Qeven
))
9853 dcb
.Parity
= EVENPARITY
;
9854 dcb
.fErrorChar
= TRUE
;
9856 else if (EQ (tem
, Qodd
))
9860 dcb
.Parity
= ODDPARITY
;
9861 dcb
.fErrorChar
= TRUE
;
9863 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9865 /* Configure stopbits. */
9866 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9867 tem
= Fplist_get (contact
, QCstopbits
);
9869 tem
= Fplist_get (p
->childp
, QCstopbits
);
9871 tem
= make_number (1);
9873 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9874 error (":stopbits must be nil (1 stopbit), 1, or 2");
9875 summary
[2] = XINT (tem
) + '0';
9876 if (XINT (tem
) == 1)
9877 dcb
.StopBits
= ONESTOPBIT
;
9878 else if (XINT (tem
) == 2)
9879 dcb
.StopBits
= TWOSTOPBITS
;
9880 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9882 /* Configure flowcontrol. */
9883 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9884 tem
= Fplist_get (contact
, QCflowcontrol
);
9886 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9887 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9888 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9889 dcb
.fOutxCtsFlow
= FALSE
;
9890 dcb
.fOutxDsrFlow
= FALSE
;
9891 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9892 dcb
.fDsrSensitivity
= FALSE
;
9893 dcb
.fTXContinueOnXoff
= FALSE
;
9896 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9897 dcb
.XonChar
= 17; /* Control-Q */
9898 dcb
.XoffChar
= 19; /* Control-S */
9901 /* Already configured. */
9903 else if (EQ (tem
, Qhw
))
9905 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9906 dcb
.fOutxCtsFlow
= TRUE
;
9908 else if (EQ (tem
, Qsw
))
9913 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9915 /* Activate configuration. */
9916 if (!SetCommState (hnd
, &dcb
))
9917 error ("SetCommState() failed");
9919 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9920 pset_childp (p
, childp2
);
9923 /* For make-pipe-process */
9925 register_aux_fd (int infd
)
9931 error ("Could not create child process");
9933 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9935 if (fd_info
[ infd
].cp
!= NULL
)
9937 error ("fd_info[fd = %d] is already in use", infd
);
9939 fd_info
[ infd
].cp
= cp
;
9940 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
9946 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9949 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9950 int fd
= process
->infd
;
9952 n
= sys_read (fd
, (char*)buf
, sz
);
9959 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9960 if (err
== EWOULDBLOCK
)
9963 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9969 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9971 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9972 int fd
= process
->outfd
;
9973 ssize_t n
= sys_write (fd
, buf
, sz
);
9975 /* 0 or more bytes written means everything went fine. */
9979 /* Negative bytes written means we got an error in errno.
9980 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9981 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9982 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9986 #endif /* HAVE_GNUTLS */