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 <http://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 *);
87 extern void dynlib_reset_last_error (void);
91 #include "epaths.h" /* for PATH_EXEC */
97 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
98 use a different name to avoid compilation problems. */
99 typedef struct _MEMORY_STATUS_EX
{
102 DWORDLONG ullTotalPhys
;
103 DWORDLONG ullAvailPhys
;
104 DWORDLONG ullTotalPageFile
;
105 DWORDLONG ullAvailPageFile
;
106 DWORDLONG ullTotalVirtual
;
107 DWORDLONG ullAvailVirtual
;
108 DWORDLONG ullAvailExtendedVirtual
;
109 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
111 /* These are here so that GDB would know about these data types. This
112 allows attaching GDB to Emacs when a fatal exception is triggered
113 and Windows pops up the "application needs to be closed" dialog.
114 At that point, _gnu_exception_handler, the top-level exception
115 handler installed by the MinGW startup code, is somewhere on the
116 call-stack of the main thread, so going to that call frame and
117 looking at the argument to _gnu_exception_handler, which is a
118 PEXCEPTION_POINTERS pointer, can reveal the exception code
119 (excptr->ExceptionRecord->ExceptionCode) and the address where the
120 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
121 well as some additional information specific to the exception. */
122 PEXCEPTION_POINTERS excptr
;
123 PEXCEPTION_RECORD excprec
;
129 #include <tlhelp32.h>
134 #if _WIN32_WINNT < 0x0500
135 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
136 /* This either is not in psapi.h or guarded by higher value of
137 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
138 defines it in psapi.h */
139 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
141 DWORD PageFaultCount
;
142 SIZE_T PeakWorkingSetSize
;
143 SIZE_T WorkingSetSize
;
144 SIZE_T QuotaPeakPagedPoolUsage
;
145 SIZE_T QuotaPagedPoolUsage
;
146 SIZE_T QuotaPeakNonPagedPoolUsage
;
147 SIZE_T QuotaNonPagedPoolUsage
;
148 SIZE_T PagefileUsage
;
149 SIZE_T PeakPagefileUsage
;
151 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
155 #include <winioctl.h>
162 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
163 define them by hand if not already defined. */
164 #ifndef SDDL_REVISION_1
165 #define SDDL_REVISION_1 1
166 #endif /* SDDL_REVISION_1 */
168 #if defined(_MSC_VER) || defined(MINGW_W64)
169 /* MSVC and MinGW64 don't provide the definition of
170 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
171 which cannot be included because it triggers conflicts with other
172 Windows API headers. So we define it here by hand. */
174 typedef struct _REPARSE_DATA_BUFFER
{
176 USHORT ReparseDataLength
;
180 USHORT SubstituteNameOffset
;
181 USHORT SubstituteNameLength
;
182 USHORT PrintNameOffset
;
183 USHORT PrintNameLength
;
186 } SymbolicLinkReparseBuffer
;
188 USHORT SubstituteNameOffset
;
189 USHORT SubstituteNameLength
;
190 USHORT PrintNameOffset
;
191 USHORT PrintNameLength
;
193 } MountPointReparseBuffer
;
196 } GenericReparseBuffer
;
198 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
200 #ifndef FILE_DEVICE_FILE_SYSTEM
201 #define FILE_DEVICE_FILE_SYSTEM 9
203 #ifndef METHOD_BUFFERED
204 #define METHOD_BUFFERED 0
206 #ifndef FILE_ANY_ACCESS
207 #define FILE_ANY_ACCESS 0x00000000
210 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
212 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
213 #ifndef FSCTL_GET_REPARSE_POINT
214 #define FSCTL_GET_REPARSE_POINT \
215 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
219 /* TCP connection support. */
220 #include <sys/socket.h>
239 #include <iphlpapi.h> /* should be after winsock2.h */
241 #include <wincrypt.h>
243 #include <c-strcase.h>
244 #include <utimens.h> /* for fdutimens */
248 #include "w32common.h"
249 #include "w32select.h"
250 #include "systime.h" /* for current_timespec, struct timespec */
251 #include "dispextern.h" /* for xstrcasecmp */
252 #include "coding.h" /* for Vlocale_coding_system */
254 #include "careadlinkat.h"
255 #include "allocator.h"
257 /* For Lisp_Process, serial_configure and serial_open. */
261 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
262 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
264 static DWORD
get_rid (PSID
);
265 static int is_symlink (const char *);
266 static char * chase_symlinks (const char *);
267 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
268 static int restore_privilege (TOKEN_PRIVILEGES
*);
269 static BOOL WINAPI
revert_to_self (void);
271 static int sys_access (const char *, int);
272 extern void *e_malloc (size_t);
273 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
274 const struct timespec
*, const sigset_t
*);
275 extern int sys_dup (int);
278 /* Initialization states.
280 WARNING: If you add any more such variables for additional APIs,
281 you MUST add initialization for them to globals_of_w32
282 below. This is because these variables might get set
283 to non-NULL values during dumping, but the dumped Emacs
284 cannot reuse those values, because it could be run on a
285 different version of the OS, where API addresses are
287 static BOOL g_b_init_is_windows_9x
;
288 static BOOL g_b_init_open_process_token
;
289 static BOOL g_b_init_get_token_information
;
290 static BOOL g_b_init_lookup_account_sid
;
291 static BOOL g_b_init_get_sid_sub_authority
;
292 static BOOL g_b_init_get_sid_sub_authority_count
;
293 static BOOL g_b_init_get_security_info
;
294 static BOOL g_b_init_get_file_security_w
;
295 static BOOL g_b_init_get_file_security_a
;
296 static BOOL g_b_init_get_security_descriptor_owner
;
297 static BOOL g_b_init_get_security_descriptor_group
;
298 static BOOL g_b_init_is_valid_sid
;
299 static BOOL g_b_init_create_toolhelp32_snapshot
;
300 static BOOL g_b_init_process32_first
;
301 static BOOL g_b_init_process32_next
;
302 static BOOL g_b_init_open_thread_token
;
303 static BOOL g_b_init_impersonate_self
;
304 static BOOL g_b_init_revert_to_self
;
305 static BOOL g_b_init_get_process_memory_info
;
306 static BOOL g_b_init_get_process_working_set_size
;
307 static BOOL g_b_init_global_memory_status
;
308 static BOOL g_b_init_global_memory_status_ex
;
309 static BOOL g_b_init_get_length_sid
;
310 static BOOL g_b_init_equal_sid
;
311 static BOOL g_b_init_copy_sid
;
312 static BOOL g_b_init_get_native_system_info
;
313 static BOOL g_b_init_get_system_times
;
314 static BOOL g_b_init_create_symbolic_link_w
;
315 static BOOL g_b_init_create_symbolic_link_a
;
316 static BOOL g_b_init_get_security_descriptor_dacl
;
317 static BOOL g_b_init_convert_sd_to_sddl
;
318 static BOOL g_b_init_convert_sddl_to_sd
;
319 static BOOL g_b_init_is_valid_security_descriptor
;
320 static BOOL g_b_init_set_file_security_w
;
321 static BOOL g_b_init_set_file_security_a
;
322 static BOOL g_b_init_set_named_security_info_w
;
323 static BOOL g_b_init_set_named_security_info_a
;
324 static BOOL g_b_init_get_adapters_info
;
326 BOOL g_b_init_compare_string_w
;
327 BOOL g_b_init_debug_break_process
;
330 BEGIN: Wrapper functions around OpenProcessToken
331 and other functions in advapi32.dll that are only
332 supported in Windows NT / 2k / XP
334 /* ** Function pointer typedefs ** */
335 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
336 HANDLE ProcessHandle
,
338 PHANDLE TokenHandle
);
339 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
341 TOKEN_INFORMATION_CLASS TokenInformationClass
,
342 LPVOID TokenInformation
,
343 DWORD TokenInformationLength
,
344 PDWORD ReturnLength
);
345 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
346 HANDLE process_handle
,
347 LPFILETIME creation_time
,
348 LPFILETIME exit_time
,
349 LPFILETIME kernel_time
,
350 LPFILETIME user_time
);
352 GetProcessTimes_Proc get_process_times_fn
= NULL
;
355 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
357 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
359 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
360 LPCTSTR lpSystemName
,
365 LPDWORD cbDomainName
,
366 PSID_NAME_USE peUse
);
367 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
370 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
372 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
374 SE_OBJECT_TYPE ObjectType
,
375 SECURITY_INFORMATION SecurityInfo
,
380 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
381 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
383 SECURITY_INFORMATION RequestedInformation
,
384 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
386 LPDWORD lpnLengthNeeded
);
387 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
389 SECURITY_INFORMATION RequestedInformation
,
390 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
392 LPDWORD lpnLengthNeeded
);
393 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
395 SECURITY_INFORMATION SecurityInformation
,
396 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
397 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
399 SECURITY_INFORMATION SecurityInformation
,
400 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
401 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
402 LPCWSTR lpObjectName
,
403 SE_OBJECT_TYPE ObjectType
,
404 SECURITY_INFORMATION SecurityInformation
,
409 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
411 SE_OBJECT_TYPE ObjectType
,
412 SECURITY_INFORMATION SecurityInformation
,
417 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
418 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
420 LPBOOL lpbOwnerDefaulted
);
421 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
422 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
424 LPBOOL lpbGroupDefaulted
);
425 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
426 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
427 LPBOOL lpbDaclPresent
,
429 LPBOOL lpbDaclDefaulted
);
430 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
432 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
434 DWORD th32ProcessID
);
435 typedef BOOL (WINAPI
* Process32First_Proc
) (
437 LPPROCESSENTRY32 lppe
);
438 typedef BOOL (WINAPI
* Process32Next_Proc
) (
440 LPPROCESSENTRY32 lppe
);
441 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
445 PHANDLE TokenHandle
);
446 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
447 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
448 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
449 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
451 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
453 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
455 PSIZE_T lpMinimumWorkingSetSize
,
456 PSIZE_T lpMaximumWorkingSetSize
);
457 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
458 LPMEMORYSTATUS lpBuffer
);
459 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
460 LPMEMORY_STATUS_EX lpBuffer
);
461 typedef BOOL (WINAPI
* CopySid_Proc
) (
462 DWORD nDestinationSidLength
,
463 PSID pDestinationSid
,
465 typedef BOOL (WINAPI
* EqualSid_Proc
) (
468 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
470 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
471 LPSYSTEM_INFO lpSystemInfo
);
472 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
473 LPFILETIME lpIdleTime
,
474 LPFILETIME lpKernelTime
,
475 LPFILETIME lpUserTime
);
476 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
477 LPCWSTR lpSymlinkFileName
,
478 LPCWSTR lpTargetFileName
,
480 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
481 LPCSTR lpSymlinkFileName
,
482 LPCSTR lpTargetFileName
,
484 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
485 LPCTSTR StringSecurityDescriptor
,
486 DWORD StringSDRevision
,
487 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
488 PULONG SecurityDescriptorSize
);
489 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
490 PSECURITY_DESCRIPTOR SecurityDescriptor
,
491 DWORD RequestedStringSDRevision
,
492 SECURITY_INFORMATION SecurityInformation
,
493 LPTSTR
*StringSecurityDescriptor
,
494 PULONG StringSecurityDescriptorLen
);
495 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
496 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
497 PIP_ADAPTER_INFO pAdapterInfo
,
500 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
501 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
502 DWORD multiByteToWideCharFlags
;
504 /* ** A utility function ** */
508 static BOOL s_b_ret
= 0;
509 OSVERSIONINFO os_ver
;
510 if (g_b_init_is_windows_9x
== 0)
512 g_b_init_is_windows_9x
= 1;
513 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
514 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
515 if (GetVersionEx (&os_ver
))
517 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
523 static Lisp_Object
ltime (ULONGLONG
);
525 /* Get total user and system times for get-internal-run-time.
526 Returns a list of integers if the times are provided by the OS
527 (NT derivatives), otherwise it returns the result of current-time. */
528 Lisp_Object
w32_get_internal_run_time (void);
531 w32_get_internal_run_time (void)
533 if (get_process_times_fn
)
535 FILETIME create
, exit
, kernel
, user
;
536 HANDLE proc
= GetCurrentProcess ();
537 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
539 LARGE_INTEGER user_int
, kernel_int
, total
;
540 user_int
.LowPart
= user
.dwLowDateTime
;
541 user_int
.HighPart
= user
.dwHighDateTime
;
542 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
543 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
544 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
545 return ltime (total
.QuadPart
);
549 return Fcurrent_time ();
552 /* ** The wrapper functions ** */
555 open_process_token (HANDLE ProcessHandle
,
559 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
560 HMODULE hm_advapi32
= NULL
;
561 if (is_windows_9x () == TRUE
)
565 if (g_b_init_open_process_token
== 0)
567 g_b_init_open_process_token
= 1;
568 hm_advapi32
= LoadLibrary ("Advapi32.dll");
569 s_pfn_Open_Process_Token
=
570 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
572 if (s_pfn_Open_Process_Token
== NULL
)
577 s_pfn_Open_Process_Token (
585 get_token_information (HANDLE TokenHandle
,
586 TOKEN_INFORMATION_CLASS TokenInformationClass
,
587 LPVOID TokenInformation
,
588 DWORD TokenInformationLength
,
591 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
592 HMODULE hm_advapi32
= NULL
;
593 if (is_windows_9x () == TRUE
)
597 if (g_b_init_get_token_information
== 0)
599 g_b_init_get_token_information
= 1;
600 hm_advapi32
= LoadLibrary ("Advapi32.dll");
601 s_pfn_Get_Token_Information
=
602 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
604 if (s_pfn_Get_Token_Information
== NULL
)
609 s_pfn_Get_Token_Information (
611 TokenInformationClass
,
613 TokenInformationLength
,
619 lookup_account_sid (LPCTSTR lpSystemName
,
624 LPDWORD cbDomainName
,
627 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
628 HMODULE hm_advapi32
= NULL
;
629 if (is_windows_9x () == TRUE
)
633 if (g_b_init_lookup_account_sid
== 0)
635 g_b_init_lookup_account_sid
= 1;
636 hm_advapi32
= LoadLibrary ("Advapi32.dll");
637 s_pfn_Lookup_Account_Sid
=
638 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
640 if (s_pfn_Lookup_Account_Sid
== NULL
)
645 s_pfn_Lookup_Account_Sid (
657 get_sid_sub_authority (PSID pSid
, DWORD n
)
659 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
660 static DWORD zero
= 0U;
661 HMODULE hm_advapi32
= NULL
;
662 if (is_windows_9x () == TRUE
)
666 if (g_b_init_get_sid_sub_authority
== 0)
668 g_b_init_get_sid_sub_authority
= 1;
669 hm_advapi32
= LoadLibrary ("Advapi32.dll");
670 s_pfn_Get_Sid_Sub_Authority
=
671 (GetSidSubAuthority_Proc
) GetProcAddress (
672 hm_advapi32
, "GetSidSubAuthority");
674 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
678 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
682 get_sid_sub_authority_count (PSID pSid
)
684 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
685 static UCHAR zero
= 0U;
686 HMODULE hm_advapi32
= NULL
;
687 if (is_windows_9x () == TRUE
)
691 if (g_b_init_get_sid_sub_authority_count
== 0)
693 g_b_init_get_sid_sub_authority_count
= 1;
694 hm_advapi32
= LoadLibrary ("Advapi32.dll");
695 s_pfn_Get_Sid_Sub_Authority_Count
=
696 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
697 hm_advapi32
, "GetSidSubAuthorityCount");
699 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
703 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
707 get_security_info (HANDLE handle
,
708 SE_OBJECT_TYPE ObjectType
,
709 SECURITY_INFORMATION SecurityInfo
,
714 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
716 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
717 HMODULE hm_advapi32
= NULL
;
718 if (is_windows_9x () == TRUE
)
722 if (g_b_init_get_security_info
== 0)
724 g_b_init_get_security_info
= 1;
725 hm_advapi32
= LoadLibrary ("Advapi32.dll");
726 s_pfn_Get_Security_Info
=
727 (GetSecurityInfo_Proc
) GetProcAddress (
728 hm_advapi32
, "GetSecurityInfo");
730 if (s_pfn_Get_Security_Info
== NULL
)
734 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
735 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
736 ppSecurityDescriptor
));
740 get_file_security (const char *lpFileName
,
741 SECURITY_INFORMATION RequestedInformation
,
742 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
744 LPDWORD lpnLengthNeeded
)
746 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
747 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
748 HMODULE hm_advapi32
= NULL
;
749 if (is_windows_9x () == TRUE
)
754 if (w32_unicode_filenames
)
756 wchar_t filename_w
[MAX_PATH
];
758 if (g_b_init_get_file_security_w
== 0)
760 g_b_init_get_file_security_w
= 1;
761 hm_advapi32
= LoadLibrary ("Advapi32.dll");
762 s_pfn_Get_File_SecurityW
=
763 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
766 if (s_pfn_Get_File_SecurityW
== NULL
)
771 filename_to_utf16 (lpFileName
, filename_w
);
772 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
773 pSecurityDescriptor
, nLength
,
778 char filename_a
[MAX_PATH
];
780 if (g_b_init_get_file_security_a
== 0)
782 g_b_init_get_file_security_a
= 1;
783 hm_advapi32
= LoadLibrary ("Advapi32.dll");
784 s_pfn_Get_File_SecurityA
=
785 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
788 if (s_pfn_Get_File_SecurityA
== NULL
)
793 filename_to_ansi (lpFileName
, filename_a
);
794 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
795 pSecurityDescriptor
, nLength
,
801 set_file_security (const char *lpFileName
,
802 SECURITY_INFORMATION SecurityInformation
,
803 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
805 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
806 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
807 HMODULE hm_advapi32
= NULL
;
808 if (is_windows_9x () == TRUE
)
813 if (w32_unicode_filenames
)
815 wchar_t filename_w
[MAX_PATH
];
817 if (g_b_init_set_file_security_w
== 0)
819 g_b_init_set_file_security_w
= 1;
820 hm_advapi32
= LoadLibrary ("Advapi32.dll");
821 s_pfn_Set_File_SecurityW
=
822 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
825 if (s_pfn_Set_File_SecurityW
== NULL
)
830 filename_to_utf16 (lpFileName
, filename_w
);
831 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
832 pSecurityDescriptor
));
836 char filename_a
[MAX_PATH
];
838 if (g_b_init_set_file_security_a
== 0)
840 g_b_init_set_file_security_a
= 1;
841 hm_advapi32
= LoadLibrary ("Advapi32.dll");
842 s_pfn_Set_File_SecurityA
=
843 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
846 if (s_pfn_Set_File_SecurityA
== NULL
)
851 filename_to_ansi (lpFileName
, filename_a
);
852 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
853 pSecurityDescriptor
));
858 set_named_security_info (LPCTSTR lpObjectName
,
859 SE_OBJECT_TYPE ObjectType
,
860 SECURITY_INFORMATION SecurityInformation
,
866 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
867 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
868 HMODULE hm_advapi32
= NULL
;
869 if (is_windows_9x () == TRUE
)
874 if (w32_unicode_filenames
)
876 wchar_t filename_w
[MAX_PATH
];
878 if (g_b_init_set_named_security_info_w
== 0)
880 g_b_init_set_named_security_info_w
= 1;
881 hm_advapi32
= LoadLibrary ("Advapi32.dll");
882 s_pfn_Set_Named_Security_InfoW
=
883 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
884 "SetNamedSecurityInfoW");
886 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
891 filename_to_utf16 (lpObjectName
, filename_w
);
892 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
893 SecurityInformation
, psidOwner
,
894 psidGroup
, pDacl
, pSacl
));
898 char filename_a
[MAX_PATH
];
900 if (g_b_init_set_named_security_info_a
== 0)
902 g_b_init_set_named_security_info_a
= 1;
903 hm_advapi32
= LoadLibrary ("Advapi32.dll");
904 s_pfn_Set_Named_Security_InfoA
=
905 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
906 "SetNamedSecurityInfoA");
908 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
913 filename_to_ansi (lpObjectName
, filename_a
);
914 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
915 SecurityInformation
, psidOwner
,
916 psidGroup
, pDacl
, pSacl
));
921 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
923 LPBOOL lpbOwnerDefaulted
)
925 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
926 HMODULE hm_advapi32
= NULL
;
927 if (is_windows_9x () == TRUE
)
932 if (g_b_init_get_security_descriptor_owner
== 0)
934 g_b_init_get_security_descriptor_owner
= 1;
935 hm_advapi32
= LoadLibrary ("Advapi32.dll");
936 s_pfn_Get_Security_Descriptor_Owner
=
937 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
938 hm_advapi32
, "GetSecurityDescriptorOwner");
940 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
945 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
950 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
952 LPBOOL lpbGroupDefaulted
)
954 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
955 HMODULE hm_advapi32
= NULL
;
956 if (is_windows_9x () == TRUE
)
961 if (g_b_init_get_security_descriptor_group
== 0)
963 g_b_init_get_security_descriptor_group
= 1;
964 hm_advapi32
= LoadLibrary ("Advapi32.dll");
965 s_pfn_Get_Security_Descriptor_Group
=
966 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
967 hm_advapi32
, "GetSecurityDescriptorGroup");
969 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
974 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
979 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
980 LPBOOL lpbDaclPresent
,
982 LPBOOL lpbDaclDefaulted
)
984 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
985 HMODULE hm_advapi32
= NULL
;
986 if (is_windows_9x () == TRUE
)
991 if (g_b_init_get_security_descriptor_dacl
== 0)
993 g_b_init_get_security_descriptor_dacl
= 1;
994 hm_advapi32
= LoadLibrary ("Advapi32.dll");
995 s_pfn_Get_Security_Descriptor_Dacl
=
996 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
997 hm_advapi32
, "GetSecurityDescriptorDacl");
999 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
1004 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
1005 lpbDaclPresent
, pDacl
,
1010 is_valid_sid (PSID sid
)
1012 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
1013 HMODULE hm_advapi32
= NULL
;
1014 if (is_windows_9x () == TRUE
)
1018 if (g_b_init_is_valid_sid
== 0)
1020 g_b_init_is_valid_sid
= 1;
1021 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1022 s_pfn_Is_Valid_Sid
=
1023 (IsValidSid_Proc
) GetProcAddress (
1024 hm_advapi32
, "IsValidSid");
1026 if (s_pfn_Is_Valid_Sid
== NULL
)
1030 return (s_pfn_Is_Valid_Sid (sid
));
1034 equal_sid (PSID sid1
, PSID sid2
)
1036 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1037 HMODULE hm_advapi32
= NULL
;
1038 if (is_windows_9x () == TRUE
)
1042 if (g_b_init_equal_sid
== 0)
1044 g_b_init_equal_sid
= 1;
1045 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1047 (EqualSid_Proc
) GetProcAddress (
1048 hm_advapi32
, "EqualSid");
1050 if (s_pfn_Equal_Sid
== NULL
)
1054 return (s_pfn_Equal_Sid (sid1
, sid2
));
1058 get_length_sid (PSID sid
)
1060 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1061 HMODULE hm_advapi32
= NULL
;
1062 if (is_windows_9x () == TRUE
)
1066 if (g_b_init_get_length_sid
== 0)
1068 g_b_init_get_length_sid
= 1;
1069 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1070 s_pfn_Get_Length_Sid
=
1071 (GetLengthSid_Proc
) GetProcAddress (
1072 hm_advapi32
, "GetLengthSid");
1074 if (s_pfn_Get_Length_Sid
== NULL
)
1078 return (s_pfn_Get_Length_Sid (sid
));
1082 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1084 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1085 HMODULE hm_advapi32
= NULL
;
1086 if (is_windows_9x () == TRUE
)
1090 if (g_b_init_copy_sid
== 0)
1092 g_b_init_copy_sid
= 1;
1093 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1095 (CopySid_Proc
) GetProcAddress (
1096 hm_advapi32
, "CopySid");
1098 if (s_pfn_Copy_Sid
== NULL
)
1102 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1106 END: Wrapper functions around OpenProcessToken
1107 and other functions in advapi32.dll that are only
1108 supported in Windows NT / 2k / XP
1112 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1114 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1115 if (is_windows_9x () != TRUE
)
1117 if (g_b_init_get_native_system_info
== 0)
1119 g_b_init_get_native_system_info
= 1;
1120 s_pfn_Get_Native_System_Info
=
1121 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1122 "GetNativeSystemInfo");
1124 if (s_pfn_Get_Native_System_Info
!= NULL
)
1125 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1128 lpSystemInfo
->dwNumberOfProcessors
= -1;
1132 get_system_times (LPFILETIME lpIdleTime
,
1133 LPFILETIME lpKernelTime
,
1134 LPFILETIME lpUserTime
)
1136 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1137 if (is_windows_9x () == TRUE
)
1141 if (g_b_init_get_system_times
== 0)
1143 g_b_init_get_system_times
= 1;
1144 s_pfn_Get_System_times
=
1145 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1148 if (s_pfn_Get_System_times
== NULL
)
1150 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1153 static BOOLEAN WINAPI
1154 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1155 LPCSTR lpTargetFileName
,
1158 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1159 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1162 if (is_windows_9x () == TRUE
)
1167 if (w32_unicode_filenames
)
1169 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1171 if (g_b_init_create_symbolic_link_w
== 0)
1173 g_b_init_create_symbolic_link_w
= 1;
1174 s_pfn_Create_Symbolic_LinkW
=
1175 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1176 "CreateSymbolicLinkW");
1178 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1184 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1185 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1186 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1187 /* If we were denied creation of the symlink, try again after
1188 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1191 TOKEN_PRIVILEGES priv_current
;
1193 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1196 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1197 restore_privilege (&priv_current
);
1204 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1206 if (g_b_init_create_symbolic_link_a
== 0)
1208 g_b_init_create_symbolic_link_a
= 1;
1209 s_pfn_Create_Symbolic_LinkA
=
1210 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1211 "CreateSymbolicLinkA");
1213 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1219 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1220 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1221 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1222 /* If we were denied creation of the symlink, try again after
1223 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1226 TOKEN_PRIVILEGES priv_current
;
1228 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1231 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1232 restore_privilege (&priv_current
);
1241 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1243 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1245 if (is_windows_9x () == TRUE
)
1251 if (g_b_init_is_valid_security_descriptor
== 0)
1253 g_b_init_is_valid_security_descriptor
= 1;
1254 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1255 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1256 "IsValidSecurityDescriptor");
1258 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1264 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1268 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1269 DWORD RequestedStringSDRevision
,
1270 SECURITY_INFORMATION SecurityInformation
,
1271 LPTSTR
*StringSecurityDescriptor
,
1272 PULONG StringSecurityDescriptorLen
)
1274 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1277 if (is_windows_9x () == TRUE
)
1283 if (g_b_init_convert_sd_to_sddl
== 0)
1285 g_b_init_convert_sd_to_sddl
= 1;
1287 s_pfn_Convert_SD_To_SDDL
=
1288 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1289 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1291 s_pfn_Convert_SD_To_SDDL
=
1292 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1293 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1296 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1302 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1303 RequestedStringSDRevision
,
1304 SecurityInformation
,
1305 StringSecurityDescriptor
,
1306 StringSecurityDescriptorLen
);
1312 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1313 DWORD StringSDRevision
,
1314 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1315 PULONG SecurityDescriptorSize
)
1317 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1320 if (is_windows_9x () == TRUE
)
1326 if (g_b_init_convert_sddl_to_sd
== 0)
1328 g_b_init_convert_sddl_to_sd
= 1;
1330 s_pfn_Convert_SDDL_To_SD
=
1331 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1332 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1334 s_pfn_Convert_SDDL_To_SD
=
1335 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1336 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1339 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1345 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1348 SecurityDescriptorSize
);
1354 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1356 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1357 HMODULE hm_iphlpapi
= NULL
;
1359 if (is_windows_9x () == TRUE
)
1360 return ERROR_NOT_SUPPORTED
;
1362 if (g_b_init_get_adapters_info
== 0)
1364 g_b_init_get_adapters_info
= 1;
1365 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1367 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1368 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1370 if (s_pfn_Get_Adapters_Info
== NULL
)
1371 return ERROR_NOT_SUPPORTED
;
1372 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1377 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1378 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1380 This is called from alloc.c:valid_pointer_p. */
1382 w32_valid_pointer_p (void *p
, int size
)
1385 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1389 unsigned char *buf
= alloca (size
);
1390 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1401 /* Here's an overview of how the Windows build supports file names
1402 that cannot be encoded by the current system codepage.
1404 From the POV of Lisp and layers of C code above the functions here,
1405 Emacs on Windows pretends that its file names are encoded in UTF-8;
1406 see encode_file and decode_file on coding.c. Any file name that is
1407 passed as a unibyte string to C functions defined here is assumed
1408 to be in UTF-8 encoding. Any file name returned by functions
1409 defined here must be in UTF-8 encoding, with only a few exceptions
1410 reserved for a couple of special cases. (Be sure to use
1411 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1412 as they can be much longer than MAX_PATH!)
1414 The UTF-8 encoded file names cannot be passed to system APIs, as
1415 Windows does not support that. Therefore, they are converted
1416 either to UTF-16 or to the ANSI codepage, depending on the value of
1417 w32-unicode-filenames, before calling any system APIs or CRT library
1418 functions. The default value of that variable is determined by the
1419 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1420 user can change that default (although I don't see why would she
1423 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1424 filename_from_utf16, and filename_from_ansi, are the workhorses of
1425 these conversions. They rely on Windows native APIs
1426 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1427 functions from coding.c here, because they allocate memory, which
1428 is a bad idea on the level of libc, which is what the functions
1429 here emulate. (If you worry about performance due to constant
1430 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1431 it was measured to take only a few microseconds on a not-so-fast
1432 machine, and second, that's exactly what the ANSI APIs we used
1433 before did anyway, because they are just thin wrappers around the
1436 The variables file-name-coding-system and default-file-name-coding-system
1437 still exist, but are actually used only when a file name needs to
1438 be converted to the ANSI codepage. This happens all the time when
1439 w32-unicode-filenames is nil, but can also happen from time to time
1440 when it is t. Otherwise, these variables have no effect on file-name
1441 encoding when w32-unicode-filenames is t; this is similar to
1442 selection-coding-system.
1444 This arrangement works very well, but it has a few gotchas and
1447 . Lisp code that encodes or decodes file names manually should
1448 normally use 'utf-8' as the coding-system on Windows,
1449 disregarding file-name-coding-system. This is a somewhat
1450 unpleasant consequence, but it cannot be avoided. Fortunately,
1451 very few Lisp packages need to do that.
1453 More generally, passing to library functions (e.g., fopen or
1454 opendir) file names already encoded in the ANSI codepage is
1455 explicitly *verboten*, as all those functions, as shadowed and
1456 emulated here, assume they will receive UTF-8 encoded file names.
1458 For the same reasons, no CRT function or Win32 API can be called
1459 directly in Emacs sources, without either converting the file
1460 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1461 some shadowing function defined here.
1463 . Environment variables stored in Vprocess_environment are encoded
1464 in the ANSI codepage, so if getenv/egetenv is used for a variable
1465 whose value is a file name or a list of directories, it needs to
1466 be converted to UTF-8, before it is used as argument to functions
1467 or decoded into a Lisp string.
1469 . File names passed to external libraries, like the image libraries
1470 and GnuTLS, need special handling. These libraries generally
1471 don't support UTF-16 or UTF-8 file names, so they must get file
1472 names encoded in the ANSI codepage. To facilitate using these
1473 libraries with file names that are not encodable in the ANSI
1474 codepage, use the function ansi_encode_filename, which will try
1475 to use the short 8+3 alias of a file name if that file name is
1476 not encodable in the ANSI codepage. See image.c and gnutls.c for
1477 examples of how this should be done.
1479 . Running subprocesses in non-ASCII directories and with non-ASCII
1480 file arguments is limited to the current codepage (even though
1481 Emacs is perfectly capable of finding an executable program file
1482 in a directory whose name cannot be encoded in the current
1483 codepage). This is because the command-line arguments are
1484 encoded _before_ they get to the w32-specific level, and the
1485 encoding is not known in advance (it doesn't have to be the
1486 current ANSI codepage), so w32proc.c functions cannot re-encode
1487 them in UTF-16. This should be fixed, but will also require
1488 changes in cmdproxy. The current limitation is not terribly bad
1489 anyway, since very few, if any, Windows console programs that are
1490 likely to be invoked by Emacs support UTF-16 encoded command
1493 . For similar reasons, server.el and emacsclient are also limited
1494 to the current ANSI codepage for now.
1496 . Emacs itself can only handle command-line arguments encoded in
1497 the current codepage.
1499 . Turning on w32-unicode-filename on Windows 9X (if it at all
1500 works) requires UNICOWS.DLL, which is thus a requirement even in
1501 non-GUI sessions, something that we previously avoided. */
1505 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1506 codepage defined by file-name-coding-system. */
1508 /* Current codepage for encoding file names. */
1509 static int file_name_codepage
;
1511 /* Initialize the codepage used for decoding file names. This is
1512 needed to undo the value recorded during dumping, which might not
1513 be correct when we run the dumped Emacs. */
1515 w32_init_file_name_codepage (void)
1517 file_name_codepage
= CP_ACP
;
1518 w32_ansi_code_page
= CP_ACP
;
1521 /* Produce a Windows ANSI codepage suitable for encoding file names.
1522 Return the information about that codepage in CP_INFO. */
1524 codepage_for_filenames (CPINFO
*cp_info
)
1526 /* A simple cache to avoid calling GetCPInfo every time we need to
1527 encode/decode a file name. The file-name encoding is not
1528 supposed to be changed too frequently, if ever. */
1529 static Lisp_Object last_file_name_encoding
;
1531 Lisp_Object current_encoding
;
1533 current_encoding
= Vfile_name_coding_system
;
1534 if (NILP (current_encoding
))
1535 current_encoding
= Vdefault_file_name_coding_system
;
1537 if (!EQ (last_file_name_encoding
, current_encoding
)
1538 || NILP (last_file_name_encoding
))
1540 /* Default to the current ANSI codepage. */
1541 file_name_codepage
= w32_ansi_code_page
;
1543 if (!NILP (current_encoding
))
1545 char *cpname
= SSDATA (SYMBOL_NAME (current_encoding
));
1546 char *cp
= NULL
, *end
;
1549 if (strncmp (cpname
, "cp", 2) == 0)
1551 else if (strncmp (cpname
, "windows-", 8) == 0)
1557 cpnum
= strtol (cp
, &end
, 10);
1558 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1559 file_name_codepage
= cpnum
;
1563 if (!file_name_codepage
)
1564 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1566 if (!GetCPInfo (file_name_codepage
, &cp
))
1568 file_name_codepage
= CP_ACP
;
1569 if (!GetCPInfo (file_name_codepage
, &cp
))
1573 /* Cache the new value. */
1574 last_file_name_encoding
= current_encoding
;
1579 return file_name_codepage
;
1583 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1585 int result
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, fn_in
,
1586 -1, fn_out
, MAX_PATH
);
1590 DWORD err
= GetLastError ();
1594 case ERROR_INVALID_FLAGS
:
1595 case ERROR_INVALID_PARAMETER
:
1598 case ERROR_INSUFFICIENT_BUFFER
:
1599 case ERROR_NO_UNICODE_TRANSLATION
:
1610 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1612 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1613 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1617 DWORD err
= GetLastError ();
1621 case ERROR_INVALID_FLAGS
:
1622 case ERROR_INVALID_PARAMETER
:
1625 case ERROR_INSUFFICIENT_BUFFER
:
1626 case ERROR_NO_UNICODE_TRANSLATION
:
1637 filename_to_ansi (const char *fn_in
, char *fn_out
)
1639 wchar_t fn_utf16
[MAX_PATH
];
1641 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1644 int codepage
= codepage_for_filenames (NULL
);
1646 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1647 fn_out
, MAX_PATH
, NULL
, NULL
);
1650 DWORD err
= GetLastError ();
1654 case ERROR_INVALID_FLAGS
:
1655 case ERROR_INVALID_PARAMETER
:
1658 case ERROR_INSUFFICIENT_BUFFER
:
1659 case ERROR_NO_UNICODE_TRANSLATION
:
1672 filename_from_ansi (const char *fn_in
, char *fn_out
)
1674 wchar_t fn_utf16
[MAX_PATH
];
1675 int codepage
= codepage_for_filenames (NULL
);
1676 int result
= pMultiByteToWideChar (codepage
, multiByteToWideCharFlags
, fn_in
,
1677 -1, fn_utf16
, MAX_PATH
);
1681 DWORD err
= GetLastError ();
1685 case ERROR_INVALID_FLAGS
:
1686 case ERROR_INVALID_PARAMETER
:
1689 case ERROR_INSUFFICIENT_BUFFER
:
1690 case ERROR_NO_UNICODE_TRANSLATION
:
1697 return filename_from_utf16 (fn_utf16
, fn_out
);
1702 /* The directory where we started, in UTF-8. */
1703 static char startup_dir
[MAX_UTF8_PATH
];
1705 /* Get the current working directory. */
1707 getcwd (char *dir
, int dirsize
)
1714 if (dirsize
<= strlen (startup_dir
))
1720 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1724 /* Emacs doesn't actually change directory itself, it stays in the
1725 same directory where it was started. */
1726 strcpy (dir
, startup_dir
);
1731 /* Emulate getloadavg. */
1733 struct load_sample
{
1740 /* Number of processors on this machine. */
1741 static unsigned num_of_processors
;
1743 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1744 static struct load_sample samples
[16*60];
1745 static int first_idx
= -1, last_idx
= -1;
1746 static int max_idx
= ARRAYELTS (samples
);
1751 int next_idx
= from
+ 1;
1753 if (next_idx
>= max_idx
)
1762 int prev_idx
= from
- 1;
1765 prev_idx
= max_idx
- 1;
1771 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1773 SYSTEM_INFO sysinfo
;
1774 FILETIME ft_idle
, ft_user
, ft_kernel
;
1776 /* Initialize the number of processors on this machine. */
1777 if (num_of_processors
<= 0)
1779 get_native_system_info (&sysinfo
);
1780 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1781 if (num_of_processors
<= 0)
1783 GetSystemInfo (&sysinfo
);
1784 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1786 if (num_of_processors
<= 0)
1787 num_of_processors
= 1;
1790 /* TODO: Take into account threads that are ready to run, by
1791 sampling the "\System\Processor Queue Length" performance
1792 counter. The code below accounts only for threads that are
1793 actually running. */
1795 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1797 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1799 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1800 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1801 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1802 *idle
= uidle
.QuadPart
;
1803 *kernel
= ukernel
.QuadPart
;
1804 *user
= uuser
.QuadPart
;
1814 /* Produce the load average for a given time interval, using the
1815 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1816 1-minute, 5-minute, or 15-minute average, respectively. */
1820 double retval
= -1.0;
1823 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1824 time_t now
= samples
[last_idx
].sample_time
;
1826 if (first_idx
!= last_idx
)
1828 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1830 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1831 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1834 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1835 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1836 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1838 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1841 if (idx
== first_idx
)
1850 getloadavg (double loadavg
[], int nelem
)
1853 ULONGLONG idle
, kernel
, user
;
1854 time_t now
= time (NULL
);
1856 /* If system time jumped back for some reason, delete all samples
1857 whose time is later than the current wall-clock time. This
1858 prevents load average figures from becoming frozen for prolonged
1859 periods of time, when system time is reset backwards. */
1862 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1864 if (last_idx
== first_idx
)
1866 first_idx
= last_idx
= -1;
1869 last_idx
= buf_prev (last_idx
);
1873 /* Store another sample. We ignore samples that are less than 1 sec
1876 || (difftime (now
, samples
[last_idx
].sample_time
)
1877 >= 1.0 - 2*DBL_EPSILON
*now
))
1879 sample_system_load (&idle
, &kernel
, &user
);
1880 last_idx
= buf_next (last_idx
);
1881 samples
[last_idx
].sample_time
= now
;
1882 samples
[last_idx
].idle
= idle
;
1883 samples
[last_idx
].kernel
= kernel
;
1884 samples
[last_idx
].user
= user
;
1885 /* If the buffer has more that 15 min worth of samples, discard
1887 if (first_idx
== -1)
1888 first_idx
= last_idx
;
1889 while (first_idx
!= last_idx
1890 && (difftime (now
, samples
[first_idx
].sample_time
)
1891 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1892 first_idx
= buf_next (first_idx
);
1895 for (elem
= 0; elem
< nelem
; elem
++)
1897 double avg
= getavg (elem
);
1901 loadavg
[elem
] = avg
;
1907 /* Emulate getpwuid, getpwnam and others. */
1909 #define PASSWD_FIELD_SIZE 256
1911 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1912 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1913 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1914 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1915 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1917 static struct passwd dflt_passwd
=
1929 static char dflt_group_name
[GNLEN
+1];
1931 static struct group dflt_group
=
1933 /* When group information is not available, we return this as the
1934 group for all files. */
1942 return dflt_passwd
.pw_uid
;
1948 /* I could imagine arguing for checking to see whether the user is
1949 in the Administrators group and returning a UID of 0 for that
1950 case, but I don't know how wise that would be in the long run. */
1957 return dflt_passwd
.pw_gid
;
1967 getpwuid (unsigned uid
)
1969 if (uid
== dflt_passwd
.pw_uid
)
1970 return &dflt_passwd
;
1975 getgrgid (gid_t gid
)
1981 getpwnam (char *name
)
1985 pw
= getpwuid (getuid ());
1989 if (xstrcasecmp (name
, pw
->pw_name
))
1996 init_user_info (void)
1998 /* Find the user's real name by opening the process token and
1999 looking up the name associated with the user-sid in that token.
2001 Use the relative portion of the identifier authority value from
2002 the user-sid as the user id value (same for group id using the
2003 primary group sid from the process token). */
2005 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
2006 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
2007 DWORD glength
= sizeof (gname
);
2008 HANDLE token
= NULL
;
2009 SID_NAME_USE user_type
;
2010 unsigned char *buf
= NULL
;
2012 TOKEN_USER user_token
;
2013 TOKEN_PRIMARY_GROUP group_token
;
2016 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
2019 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
2020 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2022 buf
= xmalloc (blen
);
2023 result
= get_token_information (token
, TokenUser
,
2024 (LPVOID
)buf
, blen
, &needed
);
2027 memcpy (&user_token
, buf
, sizeof (user_token
));
2028 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
2030 domain
, &dlength
, &user_type
);
2038 strcpy (dflt_passwd
.pw_name
, uname
);
2039 /* Determine a reasonable uid value. */
2040 if (xstrcasecmp ("administrator", uname
) == 0)
2042 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2043 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2047 /* Use the last sub-authority value of the RID, the relative
2048 portion of the SID, as user/group ID. */
2049 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2051 /* Get group id and name. */
2052 result
= get_token_information (token
, TokenPrimaryGroup
,
2053 (LPVOID
)buf
, blen
, &needed
);
2054 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2056 buf
= xrealloc (buf
, blen
= needed
);
2057 result
= get_token_information (token
, TokenPrimaryGroup
,
2058 (LPVOID
)buf
, blen
, &needed
);
2062 memcpy (&group_token
, buf
, sizeof (group_token
));
2063 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2064 dlength
= sizeof (domain
);
2065 /* If we can get at the real Primary Group name, use that.
2066 Otherwise, the default group name was already set to
2067 "None" in globals_of_w32. */
2068 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2069 gname
, &glength
, NULL
, &dlength
,
2071 strcpy (dflt_group_name
, gname
);
2074 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2077 /* If security calls are not supported (presumably because we
2078 are running under Windows 9X), fallback to this: */
2079 else if (GetUserName (uname
, &ulength
))
2081 strcpy (dflt_passwd
.pw_name
, uname
);
2082 if (xstrcasecmp ("administrator", uname
) == 0)
2083 dflt_passwd
.pw_uid
= 0;
2085 dflt_passwd
.pw_uid
= 123;
2086 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2090 strcpy (dflt_passwd
.pw_name
, "unknown");
2091 dflt_passwd
.pw_uid
= 123;
2092 dflt_passwd
.pw_gid
= 123;
2094 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2096 /* Set dir and shell from environment variables. */
2097 if (w32_unicode_filenames
)
2099 wchar_t *home
= _wgetenv (L
"HOME");
2100 wchar_t *shell
= _wgetenv (L
"SHELL");
2102 /* Ensure HOME and SHELL are defined. */
2107 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2108 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2112 char *home
= getenv ("HOME");
2113 char *shell
= getenv ("SHELL");
2119 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2120 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2125 CloseHandle (token
);
2128 static HCRYPTPROV w32_crypto_hprov
;
2130 w32_init_crypt_random (void)
2132 if (!CryptAcquireContext (&w32_crypto_hprov
, NULL
, NULL
, PROV_RSA_FULL
,
2133 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
2135 DebPrint (("CryptAcquireContext failed with error %x\n",
2137 w32_crypto_hprov
= 0;
2144 w32_init_random (void *buf
, ptrdiff_t buflen
)
2146 if (!w32_crypto_hprov
)
2147 w32_init_crypt_random ();
2148 if (w32_crypto_hprov
)
2150 if (CryptGenRandom (w32_crypto_hprov
, buflen
, (BYTE
*)buf
))
2156 /* MS-Windows 'rand' produces separate identical series for each
2157 thread, so we replace it with our version. */
2159 /* Algorithm AS183: An Efficient and Portable Pseudo-random Number
2160 Generator, by B.A. Wichmann, I.D. Hill. AS, v31, No. 2 (1982). */
2161 static int ix
= 3172, iy
= 9814, iz
= 20125;
2162 #define RAND_MAX_X 30269
2163 #define RAND_MAX_Y 30307
2164 #define RAND_MAX_Z 30323
2169 ix
= (171 * ix
) % RAND_MAX_X
;
2170 iy
= (172 * iy
) % RAND_MAX_Y
;
2171 iz
= (170 * iz
) % RAND_MAX_Z
;
2173 return (ix
+ iy
+ iz
) & 0x7fff;
2179 /* rand_as183 () gives us 15 random bits...hack together 30 bits. */
2180 return ((rand_as183 () << 15) | rand_as183 ());
2187 ix
= rand () % RAND_MAX_X
;
2188 iy
= rand () % RAND_MAX_Y
;
2189 iz
= rand () % RAND_MAX_Z
;
2192 /* Return the maximum length in bytes of a multibyte character
2193 sequence encoded in the current ANSI codepage. This is required to
2194 correctly walk the encoded file names one character at a time. */
2196 max_filename_mbslen (void)
2200 codepage_for_filenames (&cp_info
);
2201 return cp_info
.MaxCharSize
;
2204 /* Normalize filename by converting in-place all of its path
2205 separators to the separator specified by PATH_SEP. */
2208 normalize_filename (register char *fp
, char path_sep
)
2212 /* Always lower-case drive letters a-z, even if the filesystem
2213 preserves case in filenames.
2214 This is so filenames can be compared by string comparison
2215 functions that are case-sensitive. Even case-preserving filesystems
2216 do not distinguish case in drive letters. */
2219 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2227 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2233 /* Destructively turn backslashes into slashes. */
2235 dostounix_filename (register char *p
)
2237 normalize_filename (p
, '/');
2240 /* Destructively turn slashes into backslashes. */
2242 unixtodos_filename (register char *p
)
2244 normalize_filename (p
, '\\');
2247 /* Remove all CR's that are followed by a LF.
2248 (From msdos.c...probably should figure out a way to share it,
2249 although this code isn't going to ever change.) */
2251 crlf_to_lf (register int n
, register char *buf
)
2253 unsigned char *np
= (unsigned char *)buf
;
2254 unsigned char *startp
= np
;
2255 char *endp
= buf
+ n
;
2259 while (buf
< endp
- 1)
2263 if (*(++buf
) != 0x0a)
2274 /* Parse the root part of file name, if present. Return length and
2275 optionally store pointer to char after root. */
2277 parse_root (const char * name
, const char ** pPath
)
2279 const char * start
= name
;
2284 /* find the root name of the volume if given */
2285 if (isalpha (name
[0]) && name
[1] == ':')
2287 /* skip past drive specifier */
2289 if (IS_DIRECTORY_SEP (name
[0]))
2292 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2299 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2304 if (IS_DIRECTORY_SEP (name
[0]))
2311 return name
- start
;
2314 /* Get long base name for name; name is assumed to be absolute. */
2316 get_long_basename (char * name
, char * buf
, int size
)
2318 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2319 char fname_utf8
[MAX_UTF8_PATH
];
2323 /* Must be valid filename, no wild cards or other invalid characters. */
2324 if (strpbrk (name
, "*?|<>\""))
2327 if (w32_unicode_filenames
)
2329 wchar_t fname_utf16
[MAX_PATH
];
2330 WIN32_FIND_DATAW find_data_wide
;
2332 filename_to_utf16 (name
, fname_utf16
);
2333 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2334 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2335 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2339 char fname_ansi
[MAX_PATH
];
2340 WIN32_FIND_DATAA find_data_ansi
;
2342 filename_to_ansi (name
, fname_ansi
);
2343 /* If the ANSI name includes ? characters, it is not encodable
2344 in the ANSI codepage. In that case, we deliver the question
2345 marks to the caller; calling FindFirstFileA in this case
2346 could return some unrelated file name in the same
2348 if (_mbspbrk (fname_ansi
, "?"))
2350 /* Find the basename of fname_ansi. */
2351 char *p
= strrchr (fname_ansi
, '\\');
2357 cstatus
= filename_from_ansi (p
, fname_utf8
);
2361 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2362 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2363 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2367 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2368 memcpy (buf
, fname_utf8
, len
+ 1);
2372 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2373 FindClose (dir_handle
);
2378 /* Get long name for file, if possible (assumed to be absolute). */
2380 w32_get_long_filename (const char * name
, char * buf
, int size
)
2385 char full
[ MAX_UTF8_PATH
];
2388 len
= strlen (name
);
2389 if (len
>= MAX_UTF8_PATH
)
2392 /* Use local copy for destructive modification. */
2393 memcpy (full
, name
, len
+1);
2394 unixtodos_filename (full
);
2396 /* Copy root part verbatim. */
2397 len
= parse_root (full
, (const char **)&p
);
2398 memcpy (o
, full
, len
);
2403 while (p
!= NULL
&& *p
)
2406 p
= strchr (q
, '\\');
2408 len
= get_long_basename (full
, o
, size
);
2431 w32_get_short_filename (const char * name
, char * buf
, int size
)
2433 if (w32_unicode_filenames
)
2435 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2436 unsigned int retval
;
2438 filename_to_utf16 (name
, name_utf16
);
2439 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2440 if (retval
&& retval
< size
)
2441 filename_from_utf16 (short_name
, buf
);
2446 char name_ansi
[MAX_PATH
];
2448 filename_to_ansi (name
, name_ansi
);
2449 return GetShortPathNameA (name_ansi
, buf
, size
);
2453 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2454 MS-Windows ANSI codepage. If FILENAME includes characters not
2455 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2456 if it exists. This is needed because the w32 build wants to
2457 support file names outside of the system locale, but image
2458 libraries typically don't support wide (a.k.a. "Unicode") APIs
2459 required for that. */
2462 ansi_encode_filename (Lisp_Object filename
)
2464 Lisp_Object encoded_filename
;
2465 char fname
[MAX_PATH
];
2467 filename_to_ansi (SSDATA (filename
), fname
);
2468 if (_mbspbrk (fname
, "?"))
2470 char shortname
[MAX_PATH
];
2472 if (w32_get_short_filename (SSDATA (filename
), shortname
, MAX_PATH
))
2474 dostounix_filename (shortname
);
2475 encoded_filename
= build_string (shortname
);
2478 encoded_filename
= build_unibyte_string (fname
);
2481 encoded_filename
= build_unibyte_string (fname
);
2482 return encoded_filename
;
2486 is_unc_volume (const char *filename
)
2488 const char *ptr
= filename
;
2490 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2493 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2499 /* Emulate the Posix unsetenv. */
2501 unsetenv (const char *name
)
2506 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2511 name_len
= strlen (name
);
2512 /* MS docs says an environment variable cannot be longer than 32K. */
2513 if (name_len
> 32767)
2518 /* It is safe to use 'alloca' with 32K size, since the stack is at
2519 least 2MB, and we set it to 8MB in the link command line. */
2520 var
= alloca (name_len
+ 2);
2521 strncpy (var
, name
, name_len
);
2522 var
[name_len
++] = '=';
2523 var
[name_len
] = '\0';
2524 return _putenv (var
);
2527 /* MS _putenv doesn't support removing a variable when the argument
2528 does not include the '=' character, so we fix that here. */
2530 sys_putenv (char *str
)
2532 const char *const name_end
= strchr (str
, '=');
2534 if (name_end
== NULL
)
2536 /* Remove the variable from the environment. */
2537 return unsetenv (str
);
2540 if (strncmp (str
, "TZ=<", 4) == 0)
2542 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2543 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2544 and to the undocumented placeholder "ZZZ" otherwise. */
2545 bool supported_abbr
= true;
2546 for (char *p
= str
+ 4; *p
; p
++)
2548 if (('0' <= *p
&& *p
<= '9') || *p
== '-' || *p
== '+')
2549 supported_abbr
= false;
2555 abbrlen
= p
- (str
+ 4);
2556 memmove (str
+ 3, str
+ 4, abbrlen
);
2561 memset (str
+ 3, 'Z', abbrlen
);
2563 memmove (str
+ 3 + abbrlen
, p
+ 1, strlen (p
));
2569 return _putenv (str
);
2572 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2575 w32_get_resource (const char *key
, LPDWORD lpdwtype
)
2578 HKEY hrootkey
= NULL
;
2581 /* Check both the current user and the local machine to see if
2582 we have any resources. */
2584 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2588 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2589 && (lpvalue
= xmalloc (cbData
)) != NULL
2590 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2592 RegCloseKey (hrootkey
);
2598 RegCloseKey (hrootkey
);
2601 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2605 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2606 && (lpvalue
= xmalloc (cbData
)) != NULL
2607 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2609 RegCloseKey (hrootkey
);
2615 RegCloseKey (hrootkey
);
2621 /* The argv[] array holds ANSI-encoded strings, and so this function
2622 works with ANS_encoded strings. */
2624 init_environment (char ** argv
)
2626 static const char * const tempdirs
[] = {
2627 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2632 const int imax
= ARRAYELTS (tempdirs
);
2634 /* Implementation note: This function explicitly works with ANSI
2635 file names, not with UTF-8 encoded file names. This is because
2636 this function pushes variables into the Emacs's environment, and
2637 the environment variables are always assumed to be in the
2638 locale-specific encoding. Do NOT call any functions that accept
2639 UTF-8 file names from this function! */
2641 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2642 temporary files and assume "/tmp" if $TMPDIR is unset, which
2643 will break on DOS/Windows. Refuse to work if we cannot find
2644 a directory, not even "c:/", usable for that purpose. */
2645 for (i
= 0; i
< imax
; i
++)
2647 const char *tmp
= tempdirs
[i
];
2650 tmp
= getenv (tmp
+ 1);
2651 /* Note that `access' can lie to us if the directory resides on a
2652 read-only filesystem, like CD-ROM or a write-protected floppy.
2653 The only way to be really sure is to actually create a file and
2654 see if it succeeds. But I think that's too much to ask. */
2656 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2657 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2659 char * var
= alloca (strlen (tmp
) + 8);
2660 sprintf (var
, "TMPDIR=%s", tmp
);
2661 _putenv (strdup (var
));
2668 Fcons (build_string ("no usable temporary directories found!!"),
2670 "While setting TMPDIR: ");
2672 /* Check for environment variables and use registry settings if they
2673 don't exist. Fallback on default values where applicable. */
2678 char locale_name
[32];
2679 char default_home
[MAX_PATH
];
2682 static const struct env_entry
2685 const char * def_value
;
2688 /* If the default value is NULL, we will use the value from the
2689 outside environment or the Registry, but will not push the
2690 variable into the Emacs environment if it is defined neither
2691 in the Registry nor in the outside environment. */
2693 {"PRELOAD_WINSOCK", NULL
},
2694 {"emacs_dir", "C:/emacs"},
2695 {"EMACSLOADPATH", NULL
},
2696 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2697 {"EMACSDATA", NULL
},
2698 {"EMACSPATH", NULL
},
2705 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2707 /* We need to copy dflt_envvars[] and work on the copy because we
2708 don't want the dumped Emacs to inherit the values of
2709 environment variables we saw during dumping (which could be on
2710 a different system). The defaults above must be left intact. */
2711 struct env_entry env_vars
[N_ENV_VARS
];
2713 for (i
= 0; i
< N_ENV_VARS
; i
++)
2714 env_vars
[i
] = dflt_envvars
[i
];
2716 /* For backwards compatibility, check if a .emacs file exists in C:/
2717 If not, then we can try to default to the appdata directory under the
2718 user's profile, which is more likely to be writable. */
2719 if (sys_access ("C:/.emacs", F_OK
) != 0)
2721 HRESULT profile_result
;
2722 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2723 of Windows 95 and NT4 that have not been updated to include
2725 ShGetFolderPath_fn get_folder_path
;
2726 get_folder_path
= (ShGetFolderPath_fn
)
2727 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2729 if (get_folder_path
!= NULL
)
2731 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2734 /* If we can't get the appdata dir, revert to old behavior. */
2735 if (profile_result
== S_OK
)
2737 env_vars
[0].def_value
= default_home
;
2743 /* Get default locale info and use it for LANG. */
2744 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2745 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2746 locale_name
, sizeof (locale_name
)))
2748 for (i
= 0; i
< N_ENV_VARS
; i
++)
2750 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2752 env_vars
[i
].def_value
= locale_name
;
2758 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2760 /* Treat emacs_dir specially: set it unconditionally based on our
2764 char modname
[MAX_PATH
];
2766 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2768 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2772 if ((p
= _mbsrchr (modname
, '\\'))
2773 /* From bin means installed Emacs, from src means uninstalled. */
2774 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2776 char buf
[SET_ENV_BUF_SIZE
];
2777 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2780 for (p
= modname
; *p
; p
= CharNext (p
))
2781 if (*p
== '\\') *p
= '/';
2783 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2784 _putenv (strdup (buf
));
2785 /* If we are running from the Posix-like build tree, define
2786 SHELL to point to our own cmdproxy. The loop below will
2787 then disregard PATH_EXEC and the default value. */
2788 if (within_build_tree
)
2790 _snprintf (buf
, sizeof (buf
) - 1,
2791 "SHELL=%s/nt/cmdproxy.exe", modname
);
2792 _putenv (strdup (buf
));
2797 for (i
= 0; i
< N_ENV_VARS
; i
++)
2799 if (!getenv (env_vars
[i
].name
))
2802 char bufc
[SET_ENV_BUF_SIZE
];
2804 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2805 /* Also ignore empty environment variables. */
2810 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2812 /* Look for cmdproxy.exe in every directory in
2813 PATH_EXEC. FIXME: This does not find cmdproxy
2814 in nt/ when we run uninstalled. */
2815 char fname
[MAX_PATH
];
2816 const char *pstart
= PATH_EXEC
, *pend
;
2819 pend
= _mbschr (pstart
, ';');
2821 pend
= pstart
+ strlen (pstart
);
2822 /* Be defensive against series of ;;; characters. */
2825 strncpy (fname
, pstart
, pend
- pstart
);
2826 fname
[pend
- pstart
] = '/';
2827 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2828 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2830 if (sys_access (bufc
, F_OK
) == 0)
2843 /* If not found in any directory, use the
2844 default as the last resort. */
2845 lpval
= (char *)env_vars
[i
].def_value
;
2846 dwType
= REG_EXPAND_SZ
;
2852 lpval
= (char *)env_vars
[i
].def_value
;
2853 dwType
= REG_EXPAND_SZ
;
2855 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2856 Vdelayed_warnings_list
2858 (listn (CONSTYPE_HEAP
, 2,
2859 intern ("initialization"), build_string
2860 ("Use of `C:\\.emacs' without defining `HOME'\n"
2861 "in the environment is deprecated, "
2862 "see `Windows HOME' in the Emacs manual.")),
2863 Vdelayed_warnings_list
);
2868 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2870 if (dwType
== REG_EXPAND_SZ
)
2871 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2872 else if (dwType
== REG_SZ
)
2873 strcpy (buf1
, (char *)lpval
);
2874 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2876 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2878 _putenv (strdup (buf2
));
2888 /* Rebuild system configuration to reflect invoking system. */
2889 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2891 /* Another special case: on NT, the PATH variable is actually named
2892 "Path" although cmd.exe (perhaps NT itself) arranges for
2893 environment variable lookup and setting to be case insensitive.
2894 However, Emacs assumes a fully case sensitive environment, so we
2895 need to change "Path" to "PATH" to match the expectations of
2896 various elisp packages. We do this by the sneaky method of
2897 modifying the string in the C runtime environ entry.
2899 The same applies to COMSPEC. */
2902 const char *path
= "PATH=";
2903 int path_len
= strlen (path
);
2904 const char *comspec
= "COMSPEC=";
2905 int comspec_len
= strlen (comspec
);
2907 for (envp
= environ
; *envp
; envp
++)
2908 if (_strnicmp (*envp
, path
, path_len
) == 0)
2909 memcpy (*envp
, path
, path_len
);
2910 else if (_strnicmp (*envp
, comspec
, comspec_len
) == 0)
2911 memcpy (*envp
, comspec
, comspec_len
);
2913 /* Make the same modification to `process-environment' which has
2914 already been initialized in set_initial_environment. */
2915 for (Lisp_Object env
= Vprocess_environment
; CONSP (env
); env
= XCDR (env
))
2917 Lisp_Object entry
= XCAR (env
);
2918 if (_strnicmp (SDATA (entry
), path
, path_len
) == 0)
2919 for (int i
= 0; i
< path_len
; i
++)
2920 SSET (entry
, i
, path
[i
]);
2921 else if (_strnicmp (SDATA (entry
), comspec
, comspec_len
) == 0)
2922 for (int i
= 0; i
< comspec_len
; i
++)
2923 SSET (entry
, i
, comspec
[i
]);
2927 /* Remember the initial working directory for getcwd. */
2928 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2929 Does it matter anywhere in Emacs? */
2930 if (w32_unicode_filenames
)
2932 wchar_t wstartup_dir
[MAX_PATH
];
2934 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2936 filename_from_utf16 (wstartup_dir
, startup_dir
);
2940 char astartup_dir
[MAX_PATH
];
2942 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2944 filename_from_ansi (astartup_dir
, startup_dir
);
2948 static char modname
[MAX_PATH
];
2950 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2955 /* Determine if there is a middle mouse button, to allow parse_button
2956 to decide whether right mouse events should be mouse-2 or
2958 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2963 /* Called from expand-file-name when default-directory is not a string. */
2966 emacs_root_dir (void)
2968 static char root_dir
[MAX_UTF8_PATH
];
2971 p
= getenv ("emacs_dir");
2974 filename_from_ansi (p
, root_dir
);
2975 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2976 dostounix_filename (root_dir
);
2980 /* Emulate fdutimens. */
2982 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2983 TIMESPEC[0] and TIMESPEC[1], respectively.
2984 FD must be either negative -- in which case it is ignored --
2985 or a file descriptor that is open on FILE.
2986 If FD is nonnegative, then FILE can be NULL, which means
2987 use just futimes instead of utimes.
2988 If TIMESPEC is null, FAIL.
2989 Return 0 on success, -1 (setting errno) on failure. */
2992 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2999 if (fd
< 0 && !file
)
3004 /* _futime's prototype defines 2nd arg as having the type 'struct
3005 _utimbuf', while utime needs to accept 'struct utimbuf' for
3006 compatibility with Posix. So we need to use 2 different (but
3007 equivalent) types to avoid compiler warnings, sigh. */
3010 struct _utimbuf _ut
;
3012 _ut
.actime
= timespec
[0].tv_sec
;
3013 _ut
.modtime
= timespec
[1].tv_sec
;
3014 return _futime (fd
, &_ut
);
3020 ut
.actime
= timespec
[0].tv_sec
;
3021 ut
.modtime
= timespec
[1].tv_sec
;
3022 /* Call 'utime', which is implemented below, not the MS library
3023 function, which fails on directories. */
3024 return utime (file
, &ut
);
3029 /* ------------------------------------------------------------------------- */
3030 /* IO support and wrapper functions for the Windows API. */
3031 /* ------------------------------------------------------------------------- */
3033 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3034 on network directories, so we handle that case here.
3035 (Ulrich Leodolter, 1/11/95). */
3037 sys_ctime (const time_t *t
)
3039 char *str
= (char *) ctime (t
);
3040 return (str
? str
: (char *)"Sun Jan 01 00:00:00 1970");
3043 /* Emulate sleep...we could have done this with a define, but that
3044 would necessitate including windows.h in the files that used it.
3045 This is much easier. */
3047 sys_sleep (int seconds
)
3049 Sleep (seconds
* 1000);
3052 /* Internal MSVC functions for low-level descriptor munging */
3053 extern int __cdecl
_set_osfhnd (int fd
, long h
);
3054 extern int __cdecl
_free_osfhnd (int fd
);
3056 /* parallel array of private info on file handles */
3057 filedesc fd_info
[ MAXDESC
];
3059 typedef struct volume_info_data
{
3060 struct volume_info_data
* next
;
3062 /* time when info was obtained */
3065 /* actual volume info */
3074 /* Global referenced by various functions. */
3075 static volume_info_data volume_info
;
3077 /* Vector to indicate which drives are local and fixed (for which cached
3078 data never expires). */
3079 static BOOL fixed_drives
[26];
3081 /* Consider cached volume information to be stale if older than 10s,
3082 at least for non-local drives. Info for fixed drives is never stale. */
3083 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3084 #define VOLINFO_STILL_VALID( root_dir, info ) \
3085 ( ( isalpha (root_dir[0]) && \
3086 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3087 || GetTickCount () - info->timestamp < 10000 )
3089 /* Cache support functions. */
3091 /* Simple linked list with linear search is sufficient. */
3092 static volume_info_data
*volume_cache
= NULL
;
3094 static volume_info_data
*
3095 lookup_volume_info (char * root_dir
)
3097 volume_info_data
* info
;
3099 for (info
= volume_cache
; info
; info
= info
->next
)
3100 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
3106 add_volume_info (char * root_dir
, volume_info_data
* info
)
3108 info
->root_dir
= xstrdup (root_dir
);
3109 unixtodos_filename (info
->root_dir
);
3110 info
->next
= volume_cache
;
3111 volume_cache
= info
;
3115 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3116 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3117 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3118 static volume_info_data
*
3119 GetCachedVolumeInformation (char * root_dir
)
3121 volume_info_data
* info
;
3122 char default_root
[ MAX_UTF8_PATH
];
3123 char name
[MAX_PATH
+1];
3124 char type
[MAX_PATH
+1];
3126 /* NULL for root_dir means use root from current directory. */
3127 if (root_dir
== NULL
)
3129 if (w32_unicode_filenames
)
3131 wchar_t curdirw
[MAX_PATH
];
3133 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3135 filename_from_utf16 (curdirw
, default_root
);
3139 char curdira
[MAX_PATH
];
3141 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3143 filename_from_ansi (curdira
, default_root
);
3145 parse_root (default_root
, (const char **)&root_dir
);
3147 root_dir
= default_root
;
3150 /* Local fixed drives can be cached permanently. Removable drives
3151 cannot be cached permanently, since the volume name and serial
3152 number (if nothing else) can change. Remote drives should be
3153 treated as if they are removable, since there is no sure way to
3154 tell whether they are or not. Also, the UNC association of drive
3155 letters mapped to remote volumes can be changed at any time (even
3156 by other processes) without notice.
3158 As a compromise, so we can benefit from caching info for remote
3159 volumes, we use a simple expiry mechanism to invalidate cache
3160 entries that are more than ten seconds old. */
3163 /* No point doing this, because WNetGetConnection is even slower than
3164 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3165 GetDriveType is about the only call of this type which does not
3166 involve network access, and so is extremely quick). */
3168 /* Map drive letter to UNC if remote. */
3169 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3171 char remote_name
[ 256 ];
3172 char drive
[3] = { root_dir
[0], ':' };
3174 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3176 /* do something */ ;
3180 info
= lookup_volume_info (root_dir
);
3182 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3188 /* Info is not cached, or is stale. */
3189 if (w32_unicode_filenames
)
3191 wchar_t root_w
[MAX_PATH
];
3192 wchar_t name_w
[MAX_PATH
+1];
3193 wchar_t type_w
[MAX_PATH
+1];
3195 filename_to_utf16 (root_dir
, root_w
);
3196 if (!GetVolumeInformationW (root_w
,
3197 name_w
, sizeof (name_w
),
3201 type_w
, sizeof (type_w
)))
3203 /* Hmm... not really 100% correct, as these 2 are not file
3205 filename_from_utf16 (name_w
, name
);
3206 filename_from_utf16 (type_w
, type
);
3210 char root_a
[MAX_PATH
];
3211 char name_a
[MAX_PATH
+1];
3212 char type_a
[MAX_PATH
+1];
3214 filename_to_ansi (root_dir
, root_a
);
3215 if (!GetVolumeInformationA (root_a
,
3216 name_a
, sizeof (name_a
),
3220 type_a
, sizeof (type_a
)))
3222 filename_from_ansi (name_a
, name
);
3223 filename_from_ansi (type_a
, type
);
3226 /* Cache the volume information for future use, overwriting existing
3227 entry if present. */
3230 info
= xmalloc (sizeof (volume_info_data
));
3231 add_volume_info (root_dir
, info
);
3239 info
->name
= xstrdup (name
);
3240 unixtodos_filename (info
->name
);
3241 info
->serialnum
= serialnum
;
3242 info
->maxcomp
= maxcomp
;
3243 info
->flags
= flags
;
3244 info
->type
= xstrdup (type
);
3245 info
->timestamp
= GetTickCount ();
3251 /* Get information on the volume where NAME is held; set path pointer to
3252 start of pathname in NAME (past UNC header\volume header if present),
3253 if pPath is non-NULL.
3255 Note: if NAME includes symlinks, the information is for the volume
3256 of the symlink, not of its target. That's because, even though
3257 GetVolumeInformation returns information about the symlink target
3258 of its argument, we only pass the root directory to
3259 GetVolumeInformation, not the full NAME. */
3261 get_volume_info (const char * name
, const char ** pPath
)
3263 char temp
[MAX_UTF8_PATH
];
3264 char *rootname
= NULL
; /* default to current volume */
3265 volume_info_data
* info
;
3266 int root_len
= parse_root (name
, pPath
);
3271 /* Copy the root name of the volume, if given. */
3274 strncpy (temp
, name
, root_len
);
3275 temp
[root_len
] = '\0';
3276 unixtodos_filename (temp
);
3280 info
= GetCachedVolumeInformation (rootname
);
3283 /* Set global referenced by other functions. */
3284 volume_info
= *info
;
3290 /* Determine if volume is FAT format (ie. only supports short 8.3
3291 names); also set path pointer to start of pathname in name, if
3292 pPath is non-NULL. */
3294 is_fat_volume (const char * name
, const char ** pPath
)
3296 if (get_volume_info (name
, pPath
))
3297 return (volume_info
.maxcomp
== 12);
3301 /* Convert all slashes in a filename to backslashes, and map filename
3302 to a valid 8.3 name if necessary. The result is a pointer to a
3303 static buffer, so CAVEAT EMPTOR! */
3304 const char *map_w32_filename (const char *, const char **);
3307 map_w32_filename (const char * name
, const char ** pPath
)
3309 static char shortname
[MAX_UTF8_PATH
];
3310 char * str
= shortname
;
3313 const char * save_name
= name
;
3315 if (strlen (name
) >= sizeof (shortname
))
3317 /* Return a filename which will cause callers to fail. */
3318 strcpy (shortname
, "?");
3322 if (!fatal_error_in_progress
/* disable fancy processing during crash */
3323 && is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3325 register int left
= 8; /* maximum number of chars in part */
3326 register int extn
= 0; /* extension added? */
3327 register int dots
= 2; /* maximum number of dots allowed */
3330 *str
++ = *name
++; /* skip past UNC header */
3332 while ((c
= *name
++))
3339 *str
++ = (c
== ':' ? ':' : '\\');
3340 extn
= 0; /* reset extension flags */
3341 dots
= 2; /* max 2 dots */
3342 left
= 8; /* max length 8 for main part */
3347 /* Convert path components of the form .xxx to _xxx,
3348 but leave . and .. as they are. This allows .emacs
3349 to be read as _emacs, for example. */
3353 IS_DIRECTORY_SEP (*name
))
3368 extn
= 1; /* we've got an extension */
3369 left
= 3; /* 3 chars in extension */
3373 /* any embedded dots after the first are converted to _ */
3378 case '#': /* don't lose these, they're important */
3380 str
[-1] = c
; /* replace last character of part */
3384 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3386 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3388 dots
= 0; /* started a path component */
3397 strcpy (shortname
, name
);
3398 unixtodos_filename (shortname
);
3402 *pPath
= shortname
+ (path
- save_name
);
3408 is_exec (const char * name
)
3410 char * p
= strrchr (name
, '.');
3413 && (xstrcasecmp (p
, ".exe") == 0 ||
3414 xstrcasecmp (p
, ".com") == 0 ||
3415 xstrcasecmp (p
, ".bat") == 0 ||
3416 xstrcasecmp (p
, ".cmd") == 0));
3419 /* Emulate the Unix directory procedures opendir, closedir, and
3420 readdir. We rename them to sys_* names because some versions of
3421 MinGW startup code call opendir and readdir to glob wildcards, and
3422 the code that calls them doesn't grok UTF-8 encoded file names we
3423 produce in dirent->d_name[]. */
3425 struct dirent dir_static
; /* simulated directory contents */
3426 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3427 static int dir_is_fat
;
3428 static char dir_pathname
[MAX_UTF8_PATH
];
3429 static WIN32_FIND_DATAW dir_find_data_w
;
3430 static WIN32_FIND_DATAA dir_find_data_a
;
3431 #define DIR_FIND_DATA_W 1
3432 #define DIR_FIND_DATA_A 2
3433 static int last_dir_find_data
= -1;
3435 /* Support shares on a network resource as subdirectories of a read-only
3437 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3438 static HANDLE
open_unc_volume (const char *);
3439 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3440 static void close_unc_volume (HANDLE
);
3443 sys_opendir (const char *filename
)
3447 /* Opening is done by FindFirstFile. However, a read is inherent to
3448 this operation, so we defer the open until read time. */
3450 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3452 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3455 /* Note: We don't support traversal of UNC volumes via symlinks.
3456 Doing so would mean punishing 99.99% of use cases by resolving
3457 all the possible symlinks in FILENAME, recursively. */
3458 if (is_unc_volume (filename
))
3460 wnet_enum_handle
= open_unc_volume (filename
);
3461 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3465 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3472 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3473 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3474 /* Note: We don't support symlinks to file names on FAT volumes.
3475 Doing so would mean punishing 99.99% of use cases by resolving
3476 all the possible symlinks in FILENAME, recursively. */
3477 dir_is_fat
= is_fat_volume (filename
, NULL
);
3483 sys_closedir (DIR *dirp
)
3485 /* If we have a find-handle open, close it. */
3486 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3488 FindClose (dir_find_handle
);
3489 dir_find_handle
= INVALID_HANDLE_VALUE
;
3491 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3493 close_unc_volume (wnet_enum_handle
);
3494 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3496 xfree ((char *) dirp
);
3500 sys_readdir (DIR *dirp
)
3502 int downcase
= !NILP (Vw32_downcase_file_names
);
3504 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3506 if (!read_unc_volume (wnet_enum_handle
,
3507 dir_find_data_w
.cFileName
,
3508 dir_find_data_a
.cFileName
,
3512 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3513 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3515 char filename
[MAX_UTF8_PATH
];
3517 bool last_slash
= true;
3519 /* Note: We don't need to worry about dir_pathname being longer
3520 than MAX_UTF8_PATH, as sys_opendir already took care of that
3521 when it called map_w32_filename: that function will put a "?"
3522 in its return value in that case, thus failing all the calls
3524 strcpy (filename
, dir_pathname
);
3525 ln
= strlen (filename
);
3526 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3529 /* Note: No need to resolve symlinks in FILENAME, because
3530 FindFirst opens the directory that is the target of a
3532 if (w32_unicode_filenames
)
3534 wchar_t fnw
[MAX_PATH
+ 2];
3536 filename_to_utf16 (filename
, fnw
);
3538 wcscat (fnw
, L
"\\");
3540 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3544 char fna
[MAX_PATH
+ 2];
3546 filename_to_ansi (filename
, fna
);
3550 /* If FILENAME is not representable by the current ANSI
3551 codepage, we don't want FindFirstFileA to interpret the
3552 '?' characters as a wildcard. */
3553 if (_mbspbrk (fna
, "?"))
3554 dir_find_handle
= INVALID_HANDLE_VALUE
;
3556 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3559 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3561 /* Any changes in the value of errno here should be in sync
3562 with what directory_files_internal does when it calls
3564 switch (GetLastError ())
3566 /* Windows uses this value when FindFirstFile finds no
3567 files that match the wildcard. This is not supposed
3568 to happen, since our wildcard is "*", but just in
3569 case, if there's some weird empty directory with not
3570 even "." and ".." entries... */
3571 case ERROR_FILE_NOT_FOUND
:
3576 case ERROR_ACCESS_DENIED
:
3577 case ERROR_NETWORK_ACCESS_DENIED
:
3580 case ERROR_PATH_NOT_FOUND
:
3581 case ERROR_INVALID_DRIVE
:
3582 case ERROR_NOT_READY
:
3583 case ERROR_BAD_NETPATH
:
3584 case ERROR_BAD_NET_NAME
:
3591 else if (w32_unicode_filenames
)
3593 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3601 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3608 /* Emacs never uses this value, so don't bother making it match
3609 value returned by stat(). */
3610 dir_static
.d_ino
= 1;
3612 if (w32_unicode_filenames
)
3614 if (downcase
|| dir_is_fat
)
3616 wchar_t tem
[MAX_PATH
];
3618 wcscpy (tem
, dir_find_data_w
.cFileName
);
3620 filename_from_utf16 (tem
, dir_static
.d_name
);
3623 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3624 last_dir_find_data
= DIR_FIND_DATA_W
;
3630 /* If the file name in cFileName[] includes `?' characters, it
3631 means the original file name used characters that cannot be
3632 represented by the current ANSI codepage. To avoid total
3633 lossage, retrieve the short 8+3 alias of the long file
3635 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3637 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3638 /* 8+3 aliases are returned in all caps, which could break
3639 various alists that look at filenames' extensions. */
3642 else if (downcase
|| dir_is_fat
)
3643 strcpy (tem
, dir_find_data_a
.cFileName
);
3645 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3646 if (downcase
|| dir_is_fat
)
3649 filename_from_ansi (tem
, dir_static
.d_name
);
3651 last_dir_find_data
= DIR_FIND_DATA_A
;
3654 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3655 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3656 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3662 open_unc_volume (const char *path
)
3664 const char *fn
= map_w32_filename (path
, NULL
);
3668 if (w32_unicode_filenames
)
3671 wchar_t fnw
[MAX_PATH
];
3673 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3674 nrw
.dwType
= RESOURCETYPE_DISK
;
3675 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3676 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3677 nrw
.lpLocalName
= NULL
;
3678 filename_to_utf16 (fn
, fnw
);
3679 nrw
.lpRemoteName
= fnw
;
3680 nrw
.lpComment
= NULL
;
3681 nrw
.lpProvider
= NULL
;
3683 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3684 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3691 nra
.dwScope
= RESOURCE_GLOBALNET
;
3692 nra
.dwType
= RESOURCETYPE_DISK
;
3693 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3694 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3695 nra
.lpLocalName
= NULL
;
3696 filename_to_ansi (fn
, fna
);
3697 nra
.lpRemoteName
= fna
;
3698 nra
.lpComment
= NULL
;
3699 nra
.lpProvider
= NULL
;
3701 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3702 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3704 if (result
== NO_ERROR
)
3708 /* Make sure directory_files_internal reports a sensible error. */
3710 return INVALID_HANDLE_VALUE
;
3715 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3720 DWORD bufsize
= 512;
3724 if (w32_unicode_filenames
)
3729 buffer
= alloca (bufsize
);
3730 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3731 if (result
!= NO_ERROR
)
3733 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3734 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3736 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3738 wcsncpy (fname_w
, ptrw
, size
);
3743 int dbcs_p
= max_filename_mbslen () > 1;
3746 buffer
= alloca (bufsize
);
3747 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3748 if (result
!= NO_ERROR
)
3750 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3753 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3756 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3757 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3760 strncpy (fname_a
, ptra
, size
);
3768 close_unc_volume (HANDLE henum
)
3770 if (henum
!= INVALID_HANDLE_VALUE
)
3771 WNetCloseEnum (henum
);
3775 unc_volume_file_attributes (const char *path
)
3780 henum
= open_unc_volume (path
);
3781 if (henum
== INVALID_HANDLE_VALUE
)
3784 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3786 close_unc_volume (henum
);
3791 /* Ensure a network connection is authenticated. */
3793 logon_network_drive (const char *path
)
3795 char share
[MAX_UTF8_PATH
];
3802 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3803 drvtype
= DRIVE_REMOTE
;
3804 else if (path
[0] == '\0' || path
[1] != ':')
3805 drvtype
= GetDriveType (NULL
);
3812 drvtype
= GetDriveType (drive
);
3815 /* Only logon to networked drives. */
3816 if (drvtype
!= DRIVE_REMOTE
)
3820 strncpy (share
, path
, MAX_UTF8_PATH
);
3821 /* Truncate to just server and share name. */
3822 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3824 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3831 if (w32_unicode_filenames
)
3833 NETRESOURCEW resourcew
;
3834 wchar_t share_w
[MAX_PATH
];
3836 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3837 resourcew
.dwType
= RESOURCETYPE_DISK
;
3838 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3839 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3840 resourcew
.lpLocalName
= NULL
;
3841 filename_to_utf16 (share
, share_w
);
3842 resourcew
.lpRemoteName
= share_w
;
3843 resourcew
.lpProvider
= NULL
;
3845 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3849 NETRESOURCEA resourcea
;
3850 char share_a
[MAX_PATH
];
3852 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3853 resourcea
.dwType
= RESOURCETYPE_DISK
;
3854 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3855 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3856 resourcea
.lpLocalName
= NULL
;
3857 filename_to_ansi (share
, share_a
);
3858 resourcea
.lpRemoteName
= share_a
;
3859 resourcea
.lpProvider
= NULL
;
3861 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3867 case ERROR_ALREADY_ASSIGNED
:
3869 case ERROR_ACCESS_DENIED
:
3870 case ERROR_LOGON_FAILURE
:
3876 case ERROR_BAD_NET_NAME
:
3877 case ERROR_NO_NET_OR_BAD_PATH
:
3878 case ERROR_NO_NETWORK
:
3879 case ERROR_CANCELLED
:
3886 /* Emulate faccessat(2). */
3888 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3891 char fullname
[MAX_UTF8_PATH
];
3893 /* Rely on a hack: an open directory is modeled as file descriptor 0,
3894 and its actual file name is stored in dir_pathname by opendir.
3895 This is good enough for the current usage in Emacs, but is fragile. */
3896 if (dirfd
!= AT_FDCWD
3897 && !(IS_DIRECTORY_SEP (path
[0])
3898 || IS_DEVICE_SEP (path
[1])))
3900 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
3902 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
3903 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", path
)
3906 errno
= ENAMETOOLONG
;
3912 /* When dired.c calls us with F_OK and a trailing slash, it actually
3913 wants to know whether PATH is a directory. */
3914 if (IS_DIRECTORY_SEP (path
[strlen (path
) - 1]) && mode
== F_OK
)
3917 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3918 newer versions blow up when passed D_OK. */
3919 path
= map_w32_filename (path
, NULL
);
3920 /* If the last element of PATH is a symlink, we need to resolve it
3921 to get the attributes of its target file. Note: any symlinks in
3922 PATH elements other than the last one are transparently resolved
3923 by GetFileAttributes below. */
3924 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3925 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3926 path
= chase_symlinks (path
);
3928 if (w32_unicode_filenames
)
3930 wchar_t path_w
[MAX_PATH
];
3932 filename_to_utf16 (path
, path_w
);
3933 attributes
= GetFileAttributesW (path_w
);
3937 char path_a
[MAX_PATH
];
3939 filename_to_ansi (path
, path_a
);
3940 attributes
= GetFileAttributesA (path_a
);
3943 if (attributes
== -1)
3945 DWORD w32err
= GetLastError ();
3949 case ERROR_INVALID_NAME
:
3950 case ERROR_BAD_PATHNAME
:
3951 if (is_unc_volume (path
))
3953 attributes
= unc_volume_file_attributes (path
);
3954 if (attributes
== -1)
3963 case ERROR_FILE_NOT_FOUND
:
3964 case ERROR_BAD_NETPATH
:
3975 if ((mode
& X_OK
) != 0
3976 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3981 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3986 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3994 /* A special test for DIRNAME being a directory accessible by the
3995 current user. This is needed because the security permissions in
3996 directory's ACLs are not visible in the Posix-style mode bits
3997 returned by 'stat' and in attributes returned by GetFileAttributes.
3998 So a directory would seem like it's readable by the current user,
3999 but will in fact error out with EACCES when they actually try. */
4001 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
4003 char pattern
[MAX_UTF8_PATH
];
4004 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
4007 /* Network volumes need a different reading method. */
4008 if (is_unc_volume (dirname
))
4010 void *read_result
= NULL
;
4011 wchar_t fnw
[MAX_PATH
];
4014 dh
= open_unc_volume (dirname
);
4015 if (dh
!= INVALID_HANDLE_VALUE
)
4017 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
4018 close_unc_volume (dh
);
4020 /* Treat empty volumes as accessible. */
4021 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
4024 /* Note: map_w32_filename makes sure DIRNAME is not longer than
4026 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
4028 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
4029 opens the directory that is the target of a symlink. */
4030 if (w32_unicode_filenames
)
4032 wchar_t pat_w
[MAX_PATH
+ 2];
4033 WIN32_FIND_DATAW dfd_w
;
4035 filename_to_utf16 (pattern
, pat_w
);
4037 wcscat (pat_w
, L
"\\");
4038 wcscat (pat_w
, L
"*");
4039 dh
= FindFirstFileW (pat_w
, &dfd_w
);
4043 char pat_a
[MAX_PATH
+ 2];
4044 WIN32_FIND_DATAA dfd_a
;
4046 filename_to_ansi (pattern
, pat_a
);
4048 strcpy (pat_a
, "\\");
4049 strcat (pat_a
, "*");
4050 /* In case DIRNAME cannot be expressed in characters from the
4051 current ANSI codepage. */
4052 if (_mbspbrk (pat_a
, "?"))
4053 dh
= INVALID_HANDLE_VALUE
;
4055 dh
= FindFirstFileA (pat_a
, &dfd_a
);
4058 if (dh
== INVALID_HANDLE_VALUE
)
4064 /* A version of 'access' to be used locally with file names in
4065 locale-specific encoding. Does not resolve symlinks and does not
4066 support file names on FAT12 and FAT16 volumes, but that's OK, since
4067 we only invoke this function for files inside the Emacs source or
4068 installation tree, on directories (so any symlinks should have the
4069 directory bit set), and on short file names such as "C:/.emacs". */
4071 sys_access (const char *fname
, int mode
)
4073 char fname_copy
[MAX_PATH
], *p
;
4076 strcpy (fname_copy
, fname
);
4077 /* Do the equivalent of unixtodos_filename. */
4078 for (p
= fname_copy
; *p
; p
= CharNext (p
))
4082 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
4084 DWORD w32err
= GetLastError ();
4088 case ERROR_INVALID_NAME
:
4089 case ERROR_BAD_PATHNAME
:
4090 case ERROR_FILE_NOT_FOUND
:
4091 case ERROR_BAD_NETPATH
:
4100 if ((mode
& X_OK
) != 0
4101 && !(is_exec (fname_copy
)
4102 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4107 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4112 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4120 /* Shadow some MSVC runtime functions to map requests for long filenames
4121 to reasonable short names if necessary. This was originally added to
4122 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4126 sys_chdir (const char * path
)
4128 path
= map_w32_filename (path
, NULL
);
4129 if (w32_unicode_filenames
)
4131 wchar_t newdir_w
[MAX_PATH
];
4133 if (filename_to_utf16 (path
, newdir_w
) == 0)
4134 return _wchdir (newdir_w
);
4139 char newdir_a
[MAX_PATH
];
4141 if (filename_to_ansi (path
, newdir_a
) == 0)
4142 return _chdir (newdir_a
);
4148 sys_chmod (const char * path
, int mode
)
4150 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4151 if (w32_unicode_filenames
)
4153 wchar_t path_w
[MAX_PATH
];
4155 filename_to_utf16 (path
, path_w
);
4156 return _wchmod (path_w
, mode
);
4160 char path_a
[MAX_PATH
];
4162 filename_to_ansi (path
, path_a
);
4163 return _chmod (path_a
, mode
);
4168 sys_creat (const char * path
, int mode
)
4170 path
= map_w32_filename (path
, NULL
);
4171 if (w32_unicode_filenames
)
4173 wchar_t path_w
[MAX_PATH
];
4175 filename_to_utf16 (path
, path_w
);
4176 return _wcreat (path_w
, mode
);
4180 char path_a
[MAX_PATH
];
4182 filename_to_ansi (path
, path_a
);
4183 return _creat (path_a
, mode
);
4188 sys_fopen (const char * path
, const char * mode
)
4192 const char * mode_save
= mode
;
4194 /* Force all file handles to be non-inheritable. This is necessary to
4195 ensure child processes don't unwittingly inherit handles that might
4196 prevent future file access. */
4200 else if (mode
[0] == 'w' || mode
[0] == 'a')
4201 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4205 /* Only do simplistic option parsing. */
4209 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4212 else if (mode
[0] == 'b')
4217 else if (mode
[0] == 't')
4224 path
= map_w32_filename (path
, NULL
);
4225 if (w32_unicode_filenames
)
4227 wchar_t path_w
[MAX_PATH
];
4229 filename_to_utf16 (path
, path_w
);
4230 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4234 char path_a
[MAX_PATH
];
4236 filename_to_ansi (path
, path_a
);
4237 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4242 return _fdopen (fd
, mode_save
);
4245 /* This only works on NTFS volumes, but is useful to have. */
4247 sys_link (const char * old
, const char * new)
4251 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4252 wchar_t oldname_w
[MAX_PATH
];
4253 char oldname_a
[MAX_PATH
];
4255 if (old
== NULL
|| new == NULL
)
4261 strcpy (oldname
, map_w32_filename (old
, NULL
));
4262 strcpy (newname
, map_w32_filename (new, NULL
));
4264 if (w32_unicode_filenames
)
4266 filename_to_utf16 (oldname
, oldname_w
);
4267 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4268 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4272 filename_to_ansi (oldname
, oldname_a
);
4273 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4274 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4276 if (fileh
!= INVALID_HANDLE_VALUE
)
4280 /* Confusingly, the "alternate" stream name field does not apply
4281 when restoring a hard link, and instead contains the actual
4282 stream data for the link (ie. the name of the link to create).
4283 The WIN32_STREAM_ID structure before the cStreamName field is
4284 the stream header, which is then immediately followed by the
4288 WIN32_STREAM_ID wid
;
4289 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4292 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4293 indicates that flag is unsupported for CP_UTF8, and OTOH says
4294 it is the default anyway. */
4295 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4296 data
.wid
.cStreamName
, MAX_PATH
);
4299 LPVOID context
= NULL
;
4302 data
.wid
.dwStreamId
= BACKUP_LINK
;
4303 data
.wid
.dwStreamAttributes
= 0;
4304 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4305 data
.wid
.Size
.HighPart
= 0;
4306 data
.wid
.dwStreamNameSize
= 0;
4308 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4309 offsetof (WIN32_STREAM_ID
, cStreamName
)
4310 + data
.wid
.Size
.LowPart
,
4311 &wbytes
, FALSE
, FALSE
, &context
)
4312 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4319 DWORD err
= GetLastError ();
4324 case ERROR_ACCESS_DENIED
:
4325 /* This is what happens when OLDNAME is a directory,
4326 since Windows doesn't support hard links to
4327 directories. Posix says to set errno to EPERM in
4329 if (w32_unicode_filenames
)
4330 attributes
= GetFileAttributesW (oldname_w
);
4332 attributes
= GetFileAttributesA (oldname_a
);
4333 if (attributes
!= -1
4334 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4336 else if (attributes
== -1
4337 && is_unc_volume (oldname
)
4338 && unc_volume_file_attributes (oldname
) != -1)
4343 case ERROR_TOO_MANY_LINKS
:
4346 case ERROR_NOT_SAME_DEVICE
:
4356 CloseHandle (fileh
);
4365 sys_mkdir (const char * path
, mode_t mode
)
4367 path
= map_w32_filename (path
, NULL
);
4369 if (w32_unicode_filenames
)
4371 wchar_t path_w
[MAX_PATH
];
4373 filename_to_utf16 (path
, path_w
);
4374 return _wmkdir (path_w
);
4378 char path_a
[MAX_PATH
];
4380 filename_to_ansi (path
, path_a
);
4381 return _mkdir (path_a
);
4386 sys_open (const char * path
, int oflag
, int mode
)
4388 const char* mpath
= map_w32_filename (path
, NULL
);
4391 if (w32_unicode_filenames
)
4393 wchar_t mpath_w
[MAX_PATH
];
4395 filename_to_utf16 (mpath
, mpath_w
);
4396 /* If possible, try to open file without _O_CREAT, to be able to
4397 write to existing hidden and system files. Force all file
4398 handles to be non-inheritable. */
4399 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4400 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4402 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4406 char mpath_a
[MAX_PATH
];
4408 filename_to_ansi (mpath
, mpath_a
);
4409 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4410 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4412 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4419 fchmod (int fd
, mode_t mode
)
4425 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4428 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4431 bool have_temp_a
= false;
4433 /* MoveFile on Windows 95 doesn't correctly change the short file name
4434 alias in a number of circumstances (it is not easy to predict when
4435 just by looking at oldname and newname, unfortunately). In these
4436 cases, renaming through a temporary name avoids the problem.
4438 A second problem on Windows 95 is that renaming through a temp name when
4439 newname is uppercase fails (the final long name ends up in
4440 lowercase, although the short alias might be uppercase) UNLESS the
4441 long temp name is not 8.3.
4443 So, on Windows 95 we always rename through a temp name, and we make sure
4444 the temp name has a long extension to ensure correct renaming. */
4446 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4448 /* volume_info is set indirectly by map_w32_filename. */
4449 oldname_dev
= volume_info
.serialnum
;
4451 if (os_subtype
== OS_9X
)
4456 char oldname_a
[MAX_PATH
];
4458 oldname
= map_w32_filename (oldname
, NULL
);
4459 filename_to_ansi (oldname
, oldname_a
);
4460 filename_to_ansi (temp
, temp_a
);
4461 if ((o
= strrchr (oldname_a
, '\\')))
4464 o
= (char *) oldname_a
;
4466 if ((p
= strrchr (temp_a
, '\\')))
4473 /* Force temp name to require a manufactured 8.3 alias - this
4474 seems to make the second rename work properly. */
4475 sprintf (p
, "_.%s.%d", o
, i
);
4477 result
= rename (oldname_a
, temp_a
);
4479 /* This loop must surely terminate! */
4480 while (result
< 0 && errno
== EEXIST
);
4486 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4487 (at least if it is a file; don't do this for directories).
4489 Since we mustn't do this if we are just changing the case of the
4490 file name (we would end up deleting the file we are trying to
4491 rename!), we let rename detect if the destination file already
4492 exists - that way we avoid the possible pitfalls of trying to
4493 determine ourselves whether two names really refer to the same
4494 file, which is not always possible in the general case. (Consider
4495 all the permutations of shared or subst'd drives, etc.) */
4497 newname
= map_w32_filename (newname
, NULL
);
4499 /* volume_info is set indirectly by map_w32_filename. */
4500 newname_dev
= volume_info
.serialnum
;
4502 if (w32_unicode_filenames
)
4504 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4506 filename_to_utf16 (temp
, temp_w
);
4507 filename_to_utf16 (newname
, newname_w
);
4508 result
= _wrename (temp_w
, newname_w
);
4511 DWORD w32err
= GetLastError ();
4514 && newname_dev
!= oldname_dev
)
4517 /* The implementation of `rename' on Windows does not return
4518 errno = EXDEV when you are moving a directory to a
4519 different storage device (ex. logical disk). It returns
4520 EACCES instead. So here we handle such situations and
4522 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4523 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4526 else if (errno
== EEXIST
&& force
)
4528 DWORD attributes_old
;
4529 DWORD attributes_new
;
4531 if (_wchmod (newname_w
, 0666) != 0)
4533 attributes_old
= GetFileAttributesW (temp_w
);
4534 attributes_new
= GetFileAttributesW (newname_w
);
4535 if (attributes_old
!= -1 && attributes_new
!= -1
4536 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4537 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4539 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4545 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4547 if (_wrmdir (newname_w
) != 0)
4550 else if (_wunlink (newname_w
) != 0)
4552 result
= _wrename (temp_w
, newname_w
);
4554 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4555 && is_symlink (temp
))
4557 /* This is Windows prohibiting the user from creating a
4558 symlink in another place, since that requires
4566 char newname_a
[MAX_PATH
];
4569 filename_to_ansi (temp
, temp_a
);
4570 filename_to_ansi (newname
, newname_a
);
4571 result
= rename (temp_a
, newname_a
);
4574 DWORD w32err
= GetLastError ();
4577 && newname_dev
!= oldname_dev
)
4580 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4581 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4584 else if (errno
== EEXIST
&& force
)
4586 DWORD attributes_old
;
4587 DWORD attributes_new
;
4589 if (_chmod (newname_a
, 0666) != 0)
4591 attributes_old
= GetFileAttributesA (temp_a
);
4592 attributes_new
= GetFileAttributesA (newname_a
);
4593 if (attributes_old
!= -1 && attributes_new
!= -1
4594 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4595 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4597 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4603 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4605 if (_rmdir (newname_a
) != 0)
4608 else if (_unlink (newname_a
) != 0)
4610 result
= rename (temp_a
, newname_a
);
4612 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4613 && is_symlink (temp
))
4622 sys_rename (char const *old
, char const *new)
4624 return sys_rename_replace (old
, new, TRUE
);
4628 sys_rmdir (const char * path
)
4630 path
= map_w32_filename (path
, NULL
);
4632 if (w32_unicode_filenames
)
4634 wchar_t path_w
[MAX_PATH
];
4636 filename_to_utf16 (path
, path_w
);
4637 return _wrmdir (path_w
);
4641 char path_a
[MAX_PATH
];
4643 filename_to_ansi (path
, path_a
);
4644 return _rmdir (path_a
);
4649 sys_unlink (const char * path
)
4653 path
= map_w32_filename (path
, NULL
);
4655 if (w32_unicode_filenames
)
4657 wchar_t path_w
[MAX_PATH
];
4659 filename_to_utf16 (path
, path_w
);
4660 /* On Unix, unlink works without write permission. */
4661 _wchmod (path_w
, 0666);
4662 rmstatus
= _wunlink (path_w
);
4664 /* Symlinks to directories can only be deleted by _rmdir;
4665 _unlink returns EACCES. */
4668 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4669 rmstatus
= _wrmdir (path_w
);
4675 char path_a
[MAX_PATH
];
4677 filename_to_ansi (path
, path_a
);
4678 _chmod (path_a
, 0666);
4679 rmstatus
= _unlink (path_a
);
4683 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4684 rmstatus
= _rmdir (path_a
);
4692 static FILETIME utc_base_ft
;
4693 static ULONGLONG utc_base
; /* In 100ns units */
4694 static int init
= 0;
4696 #define FILETIME_TO_U64(result, ft) \
4698 ULARGE_INTEGER uiTemp; \
4699 uiTemp.LowPart = (ft).dwLowDateTime; \
4700 uiTemp.HighPart = (ft).dwHighDateTime; \
4701 result = uiTemp.QuadPart; \
4705 initialize_utc_base (void)
4707 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4716 st
.wMilliseconds
= 0;
4718 SystemTimeToFileTime (&st
, &utc_base_ft
);
4719 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4723 convert_time (FILETIME ft
)
4729 initialize_utc_base ();
4733 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4736 FILETIME_TO_U64 (tmp
, ft
);
4737 return (time_t) ((tmp
- utc_base
) / 10000000L);
4741 convert_from_time_t (time_t time
, FILETIME
* pft
)
4747 initialize_utc_base ();
4751 /* time in 100ns units since 1-Jan-1601 */
4752 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4753 pft
->dwHighDateTime
= tmp
.HighPart
;
4754 pft
->dwLowDateTime
= tmp
.LowPart
;
4757 static PSECURITY_DESCRIPTOR
4758 get_file_security_desc_by_handle (HANDLE h
)
4760 PSECURITY_DESCRIPTOR psd
= NULL
;
4762 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4763 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4765 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4766 NULL
, NULL
, NULL
, NULL
, &psd
);
4767 if (err
!= ERROR_SUCCESS
)
4773 static PSECURITY_DESCRIPTOR
4774 get_file_security_desc_by_name (const char *fname
)
4776 PSECURITY_DESCRIPTOR psd
= NULL
;
4778 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4779 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4781 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4783 err
= GetLastError ();
4784 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4788 psd
= xmalloc (sd_len
);
4789 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4801 unsigned n_subauthorities
;
4803 /* Use the last sub-authority value of the RID, the relative
4804 portion of the SID, as user/group ID. */
4805 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4806 if (n_subauthorities
< 1)
4807 return 0; /* the "World" RID */
4808 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4811 /* Caching SID and account values for faster lokup. */
4815 struct w32_id
*next
;
4817 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4820 static struct w32_id
*w32_idlist
;
4823 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4825 struct w32_id
*tail
, *found
;
4827 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4829 if (equal_sid ((PSID
)tail
->sid
, sid
))
4838 strcpy (name
, found
->name
);
4846 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4849 struct w32_id
*new_entry
;
4851 /* We don't want to leave behind stale cache from when Emacs was
4855 sid_len
= get_length_sid (sid
);
4856 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4859 new_entry
->rid
= id
;
4860 strcpy (new_entry
->name
, name
);
4861 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4862 new_entry
->next
= w32_idlist
;
4863 w32_idlist
= new_entry
;
4872 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4876 SID_NAME_USE ignore
;
4878 DWORD name_len
= sizeof (name
);
4880 DWORD domain_len
= sizeof (domain
);
4885 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4886 else if (what
== GID
)
4887 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4891 if (!result
|| !is_valid_sid (sid
))
4893 else if (!w32_cached_id (sid
, id
, nm
))
4895 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4896 domain
, &domain_len
, &ignore
)
4897 || name_len
> UNLEN
+1)
4901 *id
= get_rid (sid
);
4903 w32_add_to_cache (sid
, *id
, name
);
4910 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4912 int dflt_usr
= 0, dflt_grp
= 0;
4921 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4923 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4926 /* Consider files to belong to current user/group, if we cannot get
4927 more accurate information. */
4930 st
->st_uid
= dflt_passwd
.pw_uid
;
4931 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4935 st
->st_gid
= dflt_passwd
.pw_gid
;
4936 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4940 /* Return non-zero if NAME is a potentially slow filesystem. */
4941 int is_slow_fs (const char *);
4944 is_slow_fs (const char *name
)
4949 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4950 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4951 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4952 devtype
= GetDriveType (NULL
); /* use root of current drive */
4955 /* GetDriveType needs the root directory of the drive. */
4956 strncpy (drive_root
, name
, 2);
4957 drive_root
[2] = '\\';
4958 drive_root
[3] = '\0';
4959 devtype
= GetDriveType (drive_root
);
4961 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4964 /* If this is non-zero, the caller wants accurate information about
4965 file's owner and group, which could be expensive to get. dired.c
4966 uses this flag when needed for the job at hand. */
4967 int w32_stat_get_owner_group
;
4969 /* MSVC stat function can't cope with UNC names and has other bugs, so
4970 replace it with our own. This also allows us to calculate consistent
4971 inode values and owner/group without hacks in the main Emacs code,
4972 and support file names encoded in UTF-8. */
4975 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4977 char *name
, *save_name
, *r
;
4978 WIN32_FIND_DATAW wfd_w
;
4979 WIN32_FIND_DATAA wfd_a
;
4981 unsigned __int64 fake_inode
= 0;
4984 int rootdir
= FALSE
;
4985 PSECURITY_DESCRIPTOR psd
= NULL
;
4986 int is_a_symlink
= 0;
4987 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4988 DWORD access_rights
= 0;
4989 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4990 FILETIME ctime
, atime
, wtime
;
4991 wchar_t name_w
[MAX_PATH
];
4992 char name_a
[MAX_PATH
];
4994 if (path
== NULL
|| buf
== NULL
)
5000 save_name
= name
= (char *) map_w32_filename (path
, &path
);
5001 /* Must be valid filename, no wild cards or other invalid
5003 if (strpbrk (name
, "*?|<>\""))
5009 len
= strlen (name
);
5010 /* Allocate 1 extra byte so that we could append a slash to a root
5011 directory, down below. */
5012 name
= strcpy (alloca (len
+ 2), name
);
5014 /* Avoid a somewhat costly call to is_symlink if the filesystem
5015 doesn't support symlinks. */
5016 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5017 is_a_symlink
= is_symlink (name
);
5019 /* Plan A: Open the file and get all the necessary information via
5020 the resulting handle. This solves several issues in one blow:
5022 . retrieves attributes for the target of a symlink, if needed
5023 . gets attributes of root directories and symlinks pointing to
5024 root directories, thus avoiding the need for special-casing
5025 these and detecting them by examining the file-name format
5026 . retrieves more accurate attributes (e.g., non-zero size for
5027 some directories, esp. directories that are junction points)
5028 . correctly resolves "c:/..", "/.." and similar file names
5029 . avoids run-time penalties for 99% of use cases
5031 Plan A is always tried first, unless the user asked not to (but
5032 if the file is a symlink and we need to follow links, we try Plan
5033 A even if the user asked not to).
5035 If Plan A fails, we go to Plan B (below), where various
5036 potentially expensive techniques must be used to handle "special"
5037 files such as UNC volumes etc. */
5038 if (!(NILP (Vw32_get_true_file_attributes
)
5039 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
5040 /* Following symlinks requires getting the info by handle. */
5041 || (is_a_symlink
&& follow_symlinks
))
5043 BY_HANDLE_FILE_INFORMATION info
;
5045 if (is_a_symlink
&& !follow_symlinks
)
5046 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
5047 /* READ_CONTROL access rights are required to get security info
5048 by handle. But if the OS doesn't support security in the
5049 first place, we don't need to try. */
5050 if (is_windows_9x () != TRUE
)
5051 access_rights
|= READ_CONTROL
;
5053 if (w32_unicode_filenames
)
5055 filename_to_utf16 (name
, name_w
);
5056 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5058 /* If CreateFile fails with READ_CONTROL, try again with
5059 zero as access rights. */
5060 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5061 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
5066 filename_to_ansi (name
, name_a
);
5067 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5069 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5070 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
5073 if (fh
== INVALID_HANDLE_VALUE
)
5074 goto no_true_file_attributes
;
5076 /* This is more accurate in terms of getting the correct number
5077 of links, but is quite slow (it is noticeable when Emacs is
5078 making a list of file name completions). */
5079 if (GetFileInformationByHandle (fh
, &info
))
5081 nlinks
= info
.nNumberOfLinks
;
5082 /* Might as well use file index to fake inode values, but this
5083 is not guaranteed to be unique unless we keep a handle open
5084 all the time (even then there are situations where it is
5085 not unique). Reputedly, there are at most 48 bits of info
5086 (on NTFS, presumably less on FAT). */
5087 fake_inode
= info
.nFileIndexHigh
;
5089 fake_inode
+= info
.nFileIndexLow
;
5090 serialnum
= info
.dwVolumeSerialNumber
;
5091 fs_high
= info
.nFileSizeHigh
;
5092 fs_low
= info
.nFileSizeLow
;
5093 ctime
= info
.ftCreationTime
;
5094 atime
= info
.ftLastAccessTime
;
5095 wtime
= info
.ftLastWriteTime
;
5096 fattrs
= info
.dwFileAttributes
;
5100 /* We don't go to Plan B here, because it's not clear that
5101 it's a good idea. The only known use case where
5102 CreateFile succeeds, but GetFileInformationByHandle fails
5103 (with ERROR_INVALID_FUNCTION) is for character devices
5104 such as NUL, PRN, etc. For these, switching to Plan B is
5105 a net loss, because we lose the character device
5106 attribute returned by GetFileType below (FindFirstFile
5107 doesn't set that bit in the attributes), and the other
5108 fields don't make sense for character devices anyway.
5109 Emacs doesn't really care for non-file entities in the
5110 context of l?stat, so neither do we. */
5112 /* w32err is assigned so one could put a breakpoint here and
5113 examine its value, when GetFileInformationByHandle
5115 DWORD w32err
= GetLastError ();
5119 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5125 /* Test for a symlink before testing for a directory, since
5126 symlinks to directories have the directory bit set, but we
5127 don't want them to appear as directories. */
5128 if (is_a_symlink
&& !follow_symlinks
)
5129 buf
->st_mode
= S_IFLNK
;
5130 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5131 buf
->st_mode
= S_IFDIR
;
5134 DWORD ftype
= GetFileType (fh
);
5138 case FILE_TYPE_DISK
:
5139 buf
->st_mode
= S_IFREG
;
5141 case FILE_TYPE_PIPE
:
5142 buf
->st_mode
= S_IFIFO
;
5144 case FILE_TYPE_CHAR
:
5145 case FILE_TYPE_UNKNOWN
:
5147 buf
->st_mode
= S_IFCHR
;
5150 /* We produce the fallback owner and group data, based on the
5151 current user that runs Emacs, in the following cases:
5153 . caller didn't request owner and group info
5154 . this is Windows 9X
5155 . getting security by handle failed, and we need to produce
5156 information for the target of a symlink (this is better
5157 than producing a potentially misleading info about the
5160 If getting security by handle fails, and we don't need to
5161 resolve symlinks, we try getting security by name. */
5162 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5163 get_file_owner_and_group (NULL
, buf
);
5166 psd
= get_file_security_desc_by_handle (fh
);
5169 get_file_owner_and_group (psd
, buf
);
5172 else if (!(is_a_symlink
&& follow_symlinks
))
5174 psd
= get_file_security_desc_by_name (name
);
5175 get_file_owner_and_group (psd
, buf
);
5179 get_file_owner_and_group (NULL
, buf
);
5185 no_true_file_attributes
:
5186 /* Plan B: Either getting a handle on the file failed, or the
5187 caller explicitly asked us to not bother making this
5188 information more accurate.
5190 Implementation note: In Plan B, we never bother to resolve
5191 symlinks, even if we got here because we tried Plan A and
5192 failed. That's because, even if the caller asked for extra
5193 precision by setting Vw32_get_true_file_attributes to t,
5194 resolving symlinks requires acquiring a file handle to the
5195 symlink, which we already know will fail. And if the user
5196 did not ask for extra precision, resolving symlinks will fly
5197 in the face of that request, since the user then wants the
5198 lightweight version of the code. */
5199 rootdir
= (path
>= save_name
+ len
- 1
5200 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5202 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5203 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5204 if (IS_DIRECTORY_SEP (r
[0])
5205 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5208 /* Note: If NAME is a symlink to the root of a UNC volume
5209 (i.e. "\\SERVER"), we will not detect that here, and we will
5210 return data about the symlink as result of FindFirst below.
5211 This is unfortunate, but that marginal use case does not
5212 justify a call to chase_symlinks which would impose a penalty
5213 on all the other use cases. (We get here for symlinks to
5214 roots of UNC volumes because CreateFile above fails for them,
5215 unlike with symlinks to root directories X:\ of drives.) */
5216 if (is_unc_volume (name
))
5218 fattrs
= unc_volume_file_attributes (name
);
5222 ctime
= atime
= wtime
= utc_base_ft
;
5226 /* Make sure root directories end in a slash. */
5227 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5228 strcpy (name
+ len
, "\\");
5229 if (GetDriveType (name
) < 2)
5235 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5236 ctime
= atime
= wtime
= utc_base_ft
;
5242 /* Make sure non-root directories do NOT end in a slash,
5243 otherwise FindFirstFile might fail. */
5244 if (IS_DIRECTORY_SEP (name
[len
-1]))
5247 /* (This is hacky, but helps when doing file completions on
5248 network drives.) Optimize by using information available from
5249 active readdir if possible. */
5250 len
= strlen (dir_pathname
);
5251 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5253 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5254 && last_dir_find_data
!= -1
5255 && !(is_a_symlink
&& follow_symlinks
)
5256 /* The 2 file-name comparisons below support only ASCII
5257 characters, and will lose (compare not equal) when
5258 the file names include non-ASCII characters that are
5259 the same but for the case. However, doing this
5260 properly involves: (a) converting both file names to
5261 UTF-16, (b) lower-casing both names using CharLowerW,
5262 and (c) comparing the results; this would be quite a
5263 bit slower, whereas Plan B is for users who want
5264 lightweight albeit inaccurate version of 'stat'. */
5265 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5266 && IS_DIRECTORY_SEP (name
[len
])
5267 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5269 have_wfd
= last_dir_find_data
;
5270 /* This was the last entry returned by readdir. */
5271 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5272 wfd_w
= dir_find_data_w
;
5274 wfd_a
= dir_find_data_a
;
5278 logon_network_drive (name
);
5280 if (w32_unicode_filenames
)
5282 filename_to_utf16 (name
, name_w
);
5283 fh
= FindFirstFileW (name_w
, &wfd_w
);
5284 have_wfd
= DIR_FIND_DATA_W
;
5288 filename_to_ansi (name
, name_a
);
5289 /* If NAME includes characters not representable by
5290 the current ANSI codepage, filename_to_ansi
5291 usually replaces them with a '?'. We don't want
5292 to let FindFirstFileA interpret those as wildcards,
5293 and "succeed", returning us data from some random
5294 file in the same directory. */
5295 if (_mbspbrk (name_a
, "?"))
5296 fh
= INVALID_HANDLE_VALUE
;
5298 fh
= FindFirstFileA (name_a
, &wfd_a
);
5299 have_wfd
= DIR_FIND_DATA_A
;
5301 if (fh
== INVALID_HANDLE_VALUE
)
5308 /* Note: if NAME is a symlink, the information we get from
5309 FindFirstFile is for the symlink, not its target. */
5310 if (have_wfd
== DIR_FIND_DATA_W
)
5312 fattrs
= wfd_w
.dwFileAttributes
;
5313 ctime
= wfd_w
.ftCreationTime
;
5314 atime
= wfd_w
.ftLastAccessTime
;
5315 wtime
= wfd_w
.ftLastWriteTime
;
5316 fs_high
= wfd_w
.nFileSizeHigh
;
5317 fs_low
= wfd_w
.nFileSizeLow
;
5321 fattrs
= wfd_a
.dwFileAttributes
;
5322 ctime
= wfd_a
.ftCreationTime
;
5323 atime
= wfd_a
.ftLastAccessTime
;
5324 wtime
= wfd_a
.ftLastWriteTime
;
5325 fs_high
= wfd_a
.nFileSizeHigh
;
5326 fs_low
= wfd_a
.nFileSizeLow
;
5330 serialnum
= volume_info
.serialnum
;
5332 if (is_a_symlink
&& !follow_symlinks
)
5333 buf
->st_mode
= S_IFLNK
;
5334 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5335 buf
->st_mode
= S_IFDIR
;
5337 buf
->st_mode
= S_IFREG
;
5339 get_file_owner_and_group (NULL
, buf
);
5342 buf
->st_ino
= fake_inode
;
5344 buf
->st_dev
= serialnum
;
5345 buf
->st_rdev
= serialnum
;
5347 buf
->st_size
= fs_high
;
5348 buf
->st_size
<<= 32;
5349 buf
->st_size
+= fs_low
;
5350 buf
->st_nlink
= nlinks
;
5352 /* Convert timestamps to Unix format. */
5353 buf
->st_mtime
= convert_time (wtime
);
5354 buf
->st_atime
= convert_time (atime
);
5355 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5356 buf
->st_ctime
= convert_time (ctime
);
5357 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5359 /* determine rwx permissions */
5360 if (is_a_symlink
&& !follow_symlinks
)
5361 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5364 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5365 permission
= S_IREAD
;
5367 permission
= S_IREAD
| S_IWRITE
;
5369 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5370 permission
|= S_IEXEC
;
5371 else if (is_exec (name
))
5372 permission
|= S_IEXEC
;
5375 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5381 stat (const char * path
, struct stat
* buf
)
5383 return stat_worker (path
, buf
, 1);
5387 lstat (const char * path
, struct stat
* buf
)
5389 return stat_worker (path
, buf
, 0);
5393 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5395 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5396 This is good enough for the current usage in Emacs, but is fragile.
5398 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5399 Gnulib does this and can serve as a model. */
5400 char fullname
[MAX_UTF8_PATH
];
5404 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5406 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5407 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5410 errno
= ENAMETOOLONG
;
5416 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5419 /* Provide fstat and utime as well as stat for consistent handling of
5422 fstat (int desc
, struct stat
* buf
)
5424 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5425 BY_HANDLE_FILE_INFORMATION info
;
5426 unsigned __int64 fake_inode
;
5429 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5431 case FILE_TYPE_DISK
:
5432 buf
->st_mode
= S_IFREG
;
5433 if (!GetFileInformationByHandle (fh
, &info
))
5439 case FILE_TYPE_PIPE
:
5440 buf
->st_mode
= S_IFIFO
;
5442 case FILE_TYPE_CHAR
:
5443 case FILE_TYPE_UNKNOWN
:
5445 buf
->st_mode
= S_IFCHR
;
5447 memset (&info
, 0, sizeof (info
));
5448 info
.dwFileAttributes
= 0;
5449 info
.ftCreationTime
= utc_base_ft
;
5450 info
.ftLastAccessTime
= utc_base_ft
;
5451 info
.ftLastWriteTime
= utc_base_ft
;
5454 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5455 buf
->st_mode
= S_IFDIR
;
5457 buf
->st_nlink
= info
.nNumberOfLinks
;
5458 /* Might as well use file index to fake inode values, but this
5459 is not guaranteed to be unique unless we keep a handle open
5460 all the time (even then there are situations where it is
5461 not unique). Reputedly, there are at most 48 bits of info
5462 (on NTFS, presumably less on FAT). */
5463 fake_inode
= info
.nFileIndexHigh
;
5465 fake_inode
+= info
.nFileIndexLow
;
5467 /* MSVC defines _ino_t to be short; other libc's might not. */
5468 if (sizeof (buf
->st_ino
) == 2)
5469 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5471 buf
->st_ino
= fake_inode
;
5473 /* If the caller so requested, get the true file owner and group.
5474 Otherwise, consider the file to belong to the current user. */
5475 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5476 get_file_owner_and_group (NULL
, buf
);
5479 PSECURITY_DESCRIPTOR psd
= NULL
;
5481 psd
= get_file_security_desc_by_handle (fh
);
5484 get_file_owner_and_group (psd
, buf
);
5488 get_file_owner_and_group (NULL
, buf
);
5491 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5492 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5494 buf
->st_size
= info
.nFileSizeHigh
;
5495 buf
->st_size
<<= 32;
5496 buf
->st_size
+= info
.nFileSizeLow
;
5498 /* Convert timestamps to Unix format. */
5499 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5500 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5501 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5502 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5503 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5505 /* determine rwx permissions */
5506 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5507 permission
= S_IREAD
;
5509 permission
= S_IREAD
| S_IWRITE
;
5511 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5512 permission
|= S_IEXEC
;
5515 #if 0 /* no way of knowing the filename */
5516 char * p
= strrchr (name
, '.');
5518 (xstrcasecmp (p
, ".exe") == 0 ||
5519 xstrcasecmp (p
, ".com") == 0 ||
5520 xstrcasecmp (p
, ".bat") == 0 ||
5521 xstrcasecmp (p
, ".cmd") == 0))
5522 permission
|= S_IEXEC
;
5526 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5531 /* A version of 'utime' which handles directories as well as
5535 utime (const char *name
, struct utimbuf
*times
)
5537 struct utimbuf deftime
;
5544 deftime
.modtime
= deftime
.actime
= time (NULL
);
5548 if (w32_unicode_filenames
)
5550 wchar_t name_utf16
[MAX_PATH
];
5552 if (filename_to_utf16 (name
, name_utf16
) != 0)
5553 return -1; /* errno set by filename_to_utf16 */
5555 /* Need write access to set times. */
5556 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5557 /* If NAME specifies a directory, FILE_SHARE_DELETE
5558 allows other processes to delete files inside it,
5559 while we have the directory open. */
5560 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5561 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5565 char name_ansi
[MAX_PATH
];
5567 if (filename_to_ansi (name
, name_ansi
) != 0)
5568 return -1; /* errno set by filename_to_ansi */
5570 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5571 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5572 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5574 if (fh
!= INVALID_HANDLE_VALUE
)
5576 convert_from_time_t (times
->actime
, &atime
);
5577 convert_from_time_t (times
->modtime
, &mtime
);
5578 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5588 DWORD err
= GetLastError ();
5592 case ERROR_FILE_NOT_FOUND
:
5593 case ERROR_PATH_NOT_FOUND
:
5594 case ERROR_INVALID_DRIVE
:
5595 case ERROR_BAD_NETPATH
:
5596 case ERROR_DEV_NOT_EXIST
:
5597 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5598 file name includes ?s, i.e. translation to ANSI failed. */
5599 case ERROR_INVALID_NAME
:
5602 case ERROR_TOO_MANY_OPEN_FILES
:
5605 case ERROR_ACCESS_DENIED
:
5606 case ERROR_SHARING_VIOLATION
:
5619 sys_umask (int mode
)
5621 static int current_mask
;
5622 int retval
, arg
= 0;
5624 /* The only bit we really support is the write bit. Files are
5625 always readable on MS-Windows, and the execute bit does not exist
5627 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5628 to prevent access by other users on NTFS. */
5629 if ((mode
& S_IWRITE
) != 0)
5632 retval
= _umask (arg
);
5633 /* Merge into the return value the bits they've set the last time,
5634 which msvcrt.dll ignores and never returns. Emacs insists on its
5635 notion of mask being identical to what we return. */
5636 retval
|= (current_mask
& ~S_IWRITE
);
5637 current_mask
= mode
;
5643 /* Symlink-related functions. */
5644 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5645 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5649 symlink (char const *filename
, char const *linkname
)
5651 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5653 int dir_access
, filename_ends_in_slash
;
5655 /* Diagnostics follows Posix as much as possible. */
5656 if (filename
== NULL
|| linkname
== NULL
)
5666 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5668 errno
= ENAMETOOLONG
;
5672 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5673 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5679 /* Note: since empty FILENAME was already rejected, we can safely
5680 refer to FILENAME[1]. */
5681 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5683 /* Non-absolute FILENAME is understood as being relative to
5684 LINKNAME's directory. We need to prepend that directory to
5685 FILENAME to get correct results from faccessat below, since
5686 otherwise it will interpret FILENAME relative to the
5687 directory where the Emacs process runs. Note that
5688 make-symbolic-link always makes sure LINKNAME is a fully
5689 expanded file name. */
5690 char tem
[MAX_UTF8_PATH
];
5691 char *p
= linkfn
+ strlen (linkfn
);
5693 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5696 strncpy (tem
, linkfn
, p
- linkfn
);
5697 strcpy (tem
+ (p
- linkfn
), filename
);
5698 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5701 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5703 /* Since Windows distinguishes between symlinks to directories and
5704 to files, we provide a kludgy feature: if FILENAME doesn't
5705 exist, but ends in a slash, we create a symlink to directory. If
5706 FILENAME exists and is a directory, we always create a symlink to
5708 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5709 if (dir_access
== 0 || filename_ends_in_slash
)
5710 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5712 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5713 if (filename_ends_in_slash
)
5714 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5717 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5719 /* ENOSYS is set by create_symbolic_link, when it detects that
5720 the OS doesn't support the CreateSymbolicLink API. */
5721 if (errno
!= ENOSYS
)
5723 DWORD w32err
= GetLastError ();
5727 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5728 TGTFN point to the same file name, go figure. */
5730 case ERROR_FILE_EXISTS
:
5733 case ERROR_ACCESS_DENIED
:
5736 case ERROR_FILE_NOT_FOUND
:
5737 case ERROR_PATH_NOT_FOUND
:
5738 case ERROR_BAD_NETPATH
:
5739 case ERROR_INVALID_REPARSE_DATA
:
5742 case ERROR_DIRECTORY
:
5745 case ERROR_PRIVILEGE_NOT_HELD
:
5746 case ERROR_NOT_ALL_ASSIGNED
:
5749 case ERROR_DISK_FULL
:
5762 /* A quick inexpensive test of whether FILENAME identifies a file that
5763 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5764 must already be in the normalized form returned by
5765 map_w32_filename. If the symlink is to a directory, the
5766 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5768 Note: for repeated operations on many files, it is best to test
5769 whether the underlying volume actually supports symlinks, by
5770 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5771 avoid the call to this function if it doesn't. That's because the
5772 call to GetFileAttributes takes a non-negligible time, especially
5773 on non-local or removable filesystems. See stat_worker for an
5774 example of how to do that. */
5776 is_symlink (const char *filename
)
5779 wchar_t filename_w
[MAX_PATH
];
5780 char filename_a
[MAX_PATH
];
5781 WIN32_FIND_DATAW wfdw
;
5782 WIN32_FIND_DATAA wfda
;
5784 int attrs_mean_symlink
;
5786 if (w32_unicode_filenames
)
5788 filename_to_utf16 (filename
, filename_w
);
5789 attrs
= GetFileAttributesW (filename_w
);
5793 filename_to_ansi (filename
, filename_a
);
5794 attrs
= GetFileAttributesA (filename_a
);
5798 DWORD w32err
= GetLastError ();
5802 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5804 case ERROR_ACCESS_DENIED
:
5807 case ERROR_FILE_NOT_FOUND
:
5808 case ERROR_PATH_NOT_FOUND
:
5815 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5817 logon_network_drive (filename
);
5818 if (w32_unicode_filenames
)
5820 fh
= FindFirstFileW (filename_w
, &wfdw
);
5821 attrs_mean_symlink
=
5822 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5823 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5824 if (attrs_mean_symlink
)
5825 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5827 else if (_mbspbrk (filename_a
, "?"))
5829 /* filename_to_ansi failed to convert the file name. */
5835 fh
= FindFirstFileA (filename_a
, &wfda
);
5836 attrs_mean_symlink
=
5837 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5838 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5839 if (attrs_mean_symlink
)
5840 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5842 if (fh
== INVALID_HANDLE_VALUE
)
5845 return attrs_mean_symlink
;
5848 /* If NAME identifies a symbolic link, copy into BUF the file name of
5849 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5850 null-terminate the target name, even if it fits. Return the number
5851 of bytes copied, or -1 if NAME is not a symlink or any error was
5852 encountered while resolving it. The file name copied into BUF is
5853 encoded in the current ANSI codepage. */
5855 readlink (const char *name
, char *buf
, size_t buf_size
)
5858 TOKEN_PRIVILEGES privs
;
5859 int restore_privs
= 0;
5862 char resolved
[MAX_UTF8_PATH
];
5875 path
= map_w32_filename (name
, NULL
);
5877 if (strlen (path
) > MAX_UTF8_PATH
)
5879 errno
= ENAMETOOLONG
;
5884 if (is_windows_9x () == TRUE
5885 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5886 || !is_symlink (path
))
5889 errno
= EINVAL
; /* not a symlink */
5893 /* Done with simple tests, now we're in for some _real_ work. */
5894 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5896 /* Implementation note: From here and onward, don't return early,
5897 since that will fail to restore the original set of privileges of
5898 the calling thread. */
5900 retval
= -1; /* not too optimistic, are we? */
5902 /* Note: In the next call to CreateFile, we use zero as the 2nd
5903 argument because, when the symlink is a hidden/system file,
5904 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5905 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5906 and directory symlinks. */
5907 if (w32_unicode_filenames
)
5909 wchar_t path_w
[MAX_PATH
];
5911 filename_to_utf16 (path
, path_w
);
5912 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5913 FILE_FLAG_OPEN_REPARSE_POINT
5914 | FILE_FLAG_BACKUP_SEMANTICS
,
5919 char path_a
[MAX_PATH
];
5921 filename_to_ansi (path
, path_a
);
5922 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5923 FILE_FLAG_OPEN_REPARSE_POINT
5924 | FILE_FLAG_BACKUP_SEMANTICS
,
5927 if (sh
!= INVALID_HANDLE_VALUE
)
5929 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5930 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5933 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5934 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5937 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5941 /* Copy the link target name, in wide characters, from
5942 reparse_data, then convert it to multibyte encoding in
5943 the current locale's codepage. */
5947 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5949 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5950 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5951 size_t size_to_copy
= buf_size
;
5953 /* According to MSDN, PrintNameLength does not include the
5954 terminating null character. */
5955 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5956 memcpy (lwname
, lwname_src
, lwname_len
);
5957 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5958 filename_from_utf16 (lwname
, resolved
);
5959 dostounix_filename (resolved
);
5960 lname_size
= strlen (resolved
) + 1;
5961 if (lname_size
<= buf_size
)
5962 size_to_copy
= lname_size
;
5963 strncpy (buf
, resolved
, size_to_copy
);
5965 retval
= size_to_copy
;
5971 /* CreateFile failed. */
5972 DWORD w32err2
= GetLastError ();
5976 case ERROR_FILE_NOT_FOUND
:
5977 case ERROR_PATH_NOT_FOUND
:
5980 case ERROR_ACCESS_DENIED
:
5981 case ERROR_TOO_MANY_OPEN_FILES
:
5991 restore_privilege (&privs
);
5999 readlinkat (int fd
, char const *name
, char *buffer
,
6002 /* Rely on a hack: an open directory is modeled as file descriptor 0,
6003 as in fstatat. FIXME: Add proper support for readlinkat. */
6004 char fullname
[MAX_UTF8_PATH
];
6008 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
6011 errno
= ENAMETOOLONG
;
6017 return readlink (name
, buffer
, buffer_size
);
6020 /* If FILE is a symlink, return its target (stored in a static
6021 buffer); otherwise return FILE.
6023 This function repeatedly resolves symlinks in the last component of
6024 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6025 until it arrives at a file whose last component is not a symlink,
6026 or some error occurs. It returns the target of the last
6027 successfully resolved symlink in the chain. If it succeeds to
6028 resolve even a single symlink, the value returned is an absolute
6029 file name with backslashes (result of GetFullPathName). By
6030 contrast, if the original FILE is returned, it is unaltered.
6032 Note: This function can set errno even if it succeeds.
6034 Implementation note: we only resolve the last portion ("basename")
6035 of the argument FILE and of each following file in the chain,
6036 disregarding any possible symlinks in its leading directories.
6037 This is because Windows system calls and library functions
6038 transparently resolve symlinks in leading directories and return
6039 correct information, as long as the basename is not a symlink. */
6041 chase_symlinks (const char *file
)
6043 static char target
[MAX_UTF8_PATH
];
6044 char link
[MAX_UTF8_PATH
];
6045 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
6046 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
6047 ssize_t res
, link_len
;
6050 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
6051 return (char *)file
;
6053 if (w32_unicode_filenames
)
6055 wchar_t file_w
[MAX_PATH
];
6057 filename_to_utf16 (file
, file_w
);
6058 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
6059 return (char *)file
;
6060 filename_from_utf16 (link_w
, link
);
6064 char file_a
[MAX_PATH
];
6066 filename_to_ansi (file
, file_a
);
6067 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
6068 return (char *)file
;
6069 filename_from_ansi (link_a
, link
);
6071 link_len
= strlen (link
);
6076 /* Remove trailing slashes, as we want to resolve the last
6077 non-trivial part of the link name. */
6078 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
6079 link
[link_len
--] = '\0';
6081 res
= readlink (link
, target
, MAX_UTF8_PATH
);
6085 if (!(IS_DEVICE_SEP (target
[1])
6086 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
6088 /* Target is relative. Append it to the directory part of
6089 the symlink, then copy the result back to target. */
6090 char *p
= link
+ link_len
;
6092 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
6095 strcpy (target
, link
);
6097 /* Resolve any "." and ".." to get a fully-qualified file name
6099 if (w32_unicode_filenames
)
6101 filename_to_utf16 (target
, target_w
);
6102 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
6104 filename_from_utf16 (link_w
, link
);
6108 filename_to_ansi (target
, target_a
);
6109 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
6111 filename_from_ansi (link_a
, link
);
6113 link_len
= strlen (link
);
6115 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6117 if (loop_count
> 100)
6120 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6121 return (char *)file
;
6126 /* Posix ACL emulation. */
6129 acl_valid (acl_t acl
)
6131 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6135 acl_to_text (acl_t acl
, ssize_t
*size
)
6138 SECURITY_INFORMATION flags
=
6139 OWNER_SECURITY_INFORMATION
|
6140 GROUP_SECURITY_INFORMATION
|
6141 DACL_SECURITY_INFORMATION
;
6142 char *retval
= NULL
;
6148 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6151 /* We don't want to mix heaps, so we duplicate the string in our
6152 heap and free the one allocated by the API. */
6153 retval
= xstrdup (str_acl
);
6156 LocalFree (str_acl
);
6158 else if (errno
!= ENOTSUP
)
6165 acl_from_text (const char *acl_str
)
6167 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6173 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6176 retval
= xmalloc (sd_size
);
6177 memcpy (retval
, psd
, sd_size
);
6180 else if (errno
!= ENOTSUP
)
6187 acl_free (void *ptr
)
6194 acl_get_file (const char *fname
, acl_type_t type
)
6196 PSECURITY_DESCRIPTOR psd
= NULL
;
6197 const char *filename
;
6199 if (type
== ACL_TYPE_ACCESS
)
6202 SECURITY_INFORMATION si
=
6203 OWNER_SECURITY_INFORMATION
|
6204 GROUP_SECURITY_INFORMATION
|
6205 DACL_SECURITY_INFORMATION
;
6208 filename
= map_w32_filename (fname
, NULL
);
6209 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6210 fname
= chase_symlinks (filename
);
6215 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6216 && errno
!= ENOTSUP
)
6218 err
= GetLastError ();
6219 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6221 psd
= xmalloc (sd_len
);
6222 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6229 else if (err
== ERROR_FILE_NOT_FOUND
6230 || err
== ERROR_PATH_NOT_FOUND
6231 /* ERROR_INVALID_NAME is what we get if
6232 w32-unicode-filenames is nil and the file cannot
6233 be encoded in the current ANSI codepage. */
6234 || err
== ERROR_INVALID_NAME
)
6242 else if (type
!= ACL_TYPE_DEFAULT
)
6249 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6251 TOKEN_PRIVILEGES old1
, old2
;
6253 int st
= 0, retval
= -1;
6254 SECURITY_INFORMATION flags
= 0;
6255 PSID psidOwner
, psidGroup
;
6260 const char *filename
;
6262 if (acl_valid (acl
) != 0
6263 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6269 if (type
== ACL_TYPE_DEFAULT
)
6275 filename
= map_w32_filename (fname
, NULL
);
6276 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6277 fname
= chase_symlinks (filename
);
6281 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6284 flags
|= OWNER_SECURITY_INFORMATION
;
6285 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6288 flags
|= GROUP_SECURITY_INFORMATION
;
6289 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6292 flags
|= DACL_SECURITY_INFORMATION
;
6296 /* According to KB-245153, setting the owner will succeed if either:
6297 (1) the caller is the user who will be the new owner, and has the
6298 SE_TAKE_OWNERSHIP privilege, or
6299 (2) the caller has the SE_RESTORE privilege, in which case she can
6300 set any valid user or group as the owner
6302 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6303 privileges, and disregard any failures in obtaining them. If
6304 these privileges cannot be obtained, and do not already exist in
6305 the calling thread's security token, this function could fail
6307 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6309 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6314 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6315 DACL inheritance is involved, but it seems to preserve ownership
6316 better than SetNamedSecurityInfo, which is important e.g., in
6318 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6320 err
= GetLastError ();
6322 if (errno
!= ENOTSUP
)
6323 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6324 psidOwner
, psidGroup
, pacl
, NULL
);
6327 err
= ERROR_SUCCESS
;
6328 if (err
!= ERROR_SUCCESS
)
6330 if (errno
== ENOTSUP
)
6332 else if (err
== ERROR_INVALID_OWNER
6333 || err
== ERROR_NOT_ALL_ASSIGNED
6334 || err
== ERROR_ACCESS_DENIED
)
6336 /* Maybe the requested ACL and the one the file already has
6337 are identical, in which case we can silently ignore the
6338 failure. (And no, Windows doesn't.) */
6339 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6344 char *acl_from
= acl_to_text (current_acl
, NULL
);
6345 char *acl_to
= acl_to_text (acl
, NULL
);
6347 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6353 acl_free (acl_from
);
6356 acl_free (current_acl
);
6359 else if (err
== ERROR_FILE_NOT_FOUND
6360 || err
== ERROR_PATH_NOT_FOUND
6361 /* ERROR_INVALID_NAME is what we get if
6362 w32-unicode-filenames is nil and the file cannot be
6363 encoded in the current ANSI codepage. */
6364 || err
== ERROR_INVALID_NAME
)
6378 restore_privilege (&old2
);
6379 restore_privilege (&old1
);
6386 /* Return true if errno value ERRNUM indicates that ACLs are well
6387 supported on this system. ERRNUM should be an errno value obtained
6388 after an ACL-related system call fails. */
6390 acl_errno_valid (int errnum
)
6404 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6405 have a fixed max size for file names, so we don't need the kind of
6406 alloc/malloc/realloc dance the gnulib version does. We also don't
6407 support FD-relative symlinks. */
6409 careadlinkat (int fd
, char const *filename
,
6410 char *buffer
, size_t buffer_size
,
6411 struct allocator
const *alloc
,
6412 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6414 char linkname
[MAX_UTF8_PATH
];
6417 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6421 char *retval
= buffer
;
6423 linkname
[link_size
++] = '\0';
6424 if (link_size
> buffer_size
)
6425 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6427 memcpy (retval
, linkname
, link_size
);
6435 w32_copy_file (const char *from
, const char *to
,
6436 int keep_time
, int preserve_ownership
, int copy_acls
)
6440 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6441 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6443 /* We ignore preserve_ownership for now. */
6444 preserve_ownership
= preserve_ownership
;
6448 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6449 if (acl
== NULL
&& acl_errno_valid (errno
))
6452 if (w32_unicode_filenames
)
6454 filename_to_utf16 (from
, from_w
);
6455 filename_to_utf16 (to
, to_w
);
6456 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6460 filename_to_ansi (from
, from_a
);
6461 filename_to_ansi (to
, to_a
);
6462 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6466 /* CopyFile doesn't set errno when it fails. By far the most
6467 "popular" reason is that the target is read-only. */
6468 DWORD err
= GetLastError ();
6472 case ERROR_FILE_NOT_FOUND
:
6475 case ERROR_ACCESS_DENIED
:
6478 case ERROR_ENCRYPTION_FAILED
:
6490 /* CopyFile retains the timestamp by default. However, see
6491 "Community Additions" for CopyFile: it sounds like that is not
6492 entirely true. Testing on Windows XP confirms that modified time
6493 is copied, but creation and last-access times are not.
6495 else if (!keep_time
)
6497 struct timespec now
;
6500 if (w32_unicode_filenames
)
6502 /* Ensure file is writable while its times are set. */
6503 attributes
= GetFileAttributesW (to_w
);
6504 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6505 now
= current_timespec ();
6506 if (set_file_times (-1, to
, now
, now
))
6508 /* Restore original attributes. */
6509 SetFileAttributesW (to_w
, attributes
);
6514 /* Restore original attributes. */
6515 SetFileAttributesW (to_w
, attributes
);
6519 attributes
= GetFileAttributesA (to_a
);
6520 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6521 now
= current_timespec ();
6522 if (set_file_times (-1, to
, now
, now
))
6524 SetFileAttributesA (to_a
, attributes
);
6529 SetFileAttributesA (to_a
, attributes
);
6535 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6537 if (fail
&& acl_errno_valid (errno
))
6545 /* Support for browsing other processes and their attributes. See
6546 process.c for the Lisp bindings. */
6548 /* Helper wrapper functions. */
6550 static HANDLE WINAPI
6551 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6553 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6555 if (g_b_init_create_toolhelp32_snapshot
== 0)
6557 g_b_init_create_toolhelp32_snapshot
= 1;
6558 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6559 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6560 "CreateToolhelp32Snapshot");
6562 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6564 return INVALID_HANDLE_VALUE
;
6566 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6570 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6572 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6574 if (g_b_init_process32_first
== 0)
6576 g_b_init_process32_first
= 1;
6577 s_pfn_Process32_First
= (Process32First_Proc
)
6578 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6581 if (s_pfn_Process32_First
== NULL
)
6585 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6589 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6591 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6593 if (g_b_init_process32_next
== 0)
6595 g_b_init_process32_next
= 1;
6596 s_pfn_Process32_Next
= (Process32Next_Proc
)
6597 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6600 if (s_pfn_Process32_Next
== NULL
)
6604 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6608 open_thread_token (HANDLE ThreadHandle
,
6609 DWORD DesiredAccess
,
6611 PHANDLE TokenHandle
)
6613 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6614 HMODULE hm_advapi32
= NULL
;
6615 if (is_windows_9x () == TRUE
)
6617 SetLastError (ERROR_NOT_SUPPORTED
);
6620 if (g_b_init_open_thread_token
== 0)
6622 g_b_init_open_thread_token
= 1;
6623 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6624 s_pfn_Open_Thread_Token
=
6625 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6627 if (s_pfn_Open_Thread_Token
== NULL
)
6629 SetLastError (ERROR_NOT_SUPPORTED
);
6633 s_pfn_Open_Thread_Token (
6642 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6644 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6645 HMODULE hm_advapi32
= NULL
;
6646 if (is_windows_9x () == TRUE
)
6650 if (g_b_init_impersonate_self
== 0)
6652 g_b_init_impersonate_self
= 1;
6653 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6654 s_pfn_Impersonate_Self
=
6655 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6657 if (s_pfn_Impersonate_Self
== NULL
)
6661 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6665 revert_to_self (void)
6667 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6668 HMODULE hm_advapi32
= NULL
;
6669 if (is_windows_9x () == TRUE
)
6673 if (g_b_init_revert_to_self
== 0)
6675 g_b_init_revert_to_self
= 1;
6676 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6677 s_pfn_Revert_To_Self
=
6678 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6680 if (s_pfn_Revert_To_Self
== NULL
)
6684 return s_pfn_Revert_To_Self ();
6688 get_process_memory_info (HANDLE h_proc
,
6689 PPROCESS_MEMORY_COUNTERS mem_counters
,
6692 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6693 HMODULE hm_psapi
= NULL
;
6694 if (is_windows_9x () == TRUE
)
6698 if (g_b_init_get_process_memory_info
== 0)
6700 g_b_init_get_process_memory_info
= 1;
6701 hm_psapi
= LoadLibrary ("Psapi.dll");
6703 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6704 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6706 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6710 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6714 get_process_working_set_size (HANDLE h_proc
,
6718 static GetProcessWorkingSetSize_Proc
6719 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6721 if (is_windows_9x () == TRUE
)
6725 if (g_b_init_get_process_working_set_size
== 0)
6727 g_b_init_get_process_working_set_size
= 1;
6728 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6729 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6730 "GetProcessWorkingSetSize");
6732 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6736 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6740 global_memory_status (MEMORYSTATUS
*buf
)
6742 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6744 if (is_windows_9x () == TRUE
)
6748 if (g_b_init_global_memory_status
== 0)
6750 g_b_init_global_memory_status
= 1;
6751 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6752 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6753 "GlobalMemoryStatus");
6755 if (s_pfn_Global_Memory_Status
== NULL
)
6759 return s_pfn_Global_Memory_Status (buf
);
6763 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6765 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6767 if (is_windows_9x () == TRUE
)
6771 if (g_b_init_global_memory_status_ex
== 0)
6773 g_b_init_global_memory_status_ex
= 1;
6774 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6775 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6776 "GlobalMemoryStatusEx");
6778 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6782 return s_pfn_Global_Memory_Status_Ex (buf
);
6786 list_system_processes (void)
6788 Lisp_Object proclist
= Qnil
;
6791 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6793 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6795 PROCESSENTRY32 proc_entry
;
6799 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6800 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6801 res
= process32_next (h_snapshot
, &proc_entry
))
6803 proc_id
= proc_entry
.th32ProcessID
;
6804 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6807 CloseHandle (h_snapshot
);
6808 proclist
= Fnreverse (proclist
);
6815 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6817 TOKEN_PRIVILEGES priv
;
6818 DWORD priv_size
= sizeof (priv
);
6819 DWORD opriv_size
= sizeof (*old_priv
);
6820 HANDLE h_token
= NULL
;
6821 HANDLE h_thread
= GetCurrentThread ();
6825 res
= open_thread_token (h_thread
,
6826 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6828 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6830 if (impersonate_self (SecurityImpersonation
))
6831 res
= open_thread_token (h_thread
,
6832 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6837 priv
.PrivilegeCount
= 1;
6838 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6839 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6840 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6841 old_priv
, &opriv_size
)
6842 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6846 CloseHandle (h_token
);
6852 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6854 DWORD priv_size
= sizeof (*priv
);
6855 HANDLE h_token
= NULL
;
6858 if (open_thread_token (GetCurrentThread (),
6859 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6862 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6863 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6867 CloseHandle (h_token
);
6873 ltime (ULONGLONG time_100ns
)
6875 ULONGLONG time_sec
= time_100ns
/ 10000000;
6876 int subsec
= time_100ns
% 10000000;
6877 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6878 subsec
/ 10, subsec
% 10 * 100000);
6881 #define U64_TO_LISP_TIME(time) ltime (time)
6884 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6885 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6888 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6889 ULONGLONG tem1
, tem2
, tem3
, tem
;
6892 || !get_process_times_fn
6893 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6894 &ft_kernel
, &ft_user
))
6897 GetSystemTimeAsFileTime (&ft_current
);
6899 FILETIME_TO_U64 (tem1
, ft_kernel
);
6900 *stime
= U64_TO_LISP_TIME (tem1
);
6902 FILETIME_TO_U64 (tem2
, ft_user
);
6903 *utime
= U64_TO_LISP_TIME (tem2
);
6906 *ttime
= U64_TO_LISP_TIME (tem3
);
6908 FILETIME_TO_U64 (tem
, ft_creation
);
6909 /* Process no 4 (System) returns zero creation time. */
6912 *ctime
= U64_TO_LISP_TIME (tem
);
6916 FILETIME_TO_U64 (tem3
, ft_current
);
6917 tem
= (tem3
- utc_base
) - tem
;
6919 *etime
= U64_TO_LISP_TIME (tem
);
6923 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6934 system_process_attributes (Lisp_Object pid
)
6936 Lisp_Object attrs
= Qnil
;
6937 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6938 HANDLE h_snapshot
, h_proc
;
6941 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6942 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6943 DWORD glength
= sizeof (gname
);
6944 HANDLE token
= NULL
;
6945 SID_NAME_USE user_type
;
6946 unsigned char *buf
= NULL
;
6948 TOKEN_USER user_token
;
6949 TOKEN_PRIMARY_GROUP group_token
;
6952 PROCESS_MEMORY_COUNTERS mem
;
6953 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6954 SIZE_T minrss
, maxrss
;
6956 MEMORY_STATUS_EX memstex
;
6957 double totphys
= 0.0;
6958 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6960 BOOL result
= FALSE
;
6962 CHECK_NUMBER_OR_FLOAT (pid
);
6963 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6965 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6967 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6972 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6973 for (res
= process32_first (h_snapshot
, &pe
); res
;
6974 res
= process32_next (h_snapshot
, &pe
))
6976 if (proc_id
== pe
.th32ProcessID
)
6979 decoded_cmd
= build_string ("Idle");
6982 /* Decode the command name from locale-specific
6984 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6987 code_convert_string_norecord (cmd_str
,
6988 Vlocale_coding_system
, 0);
6990 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6991 attrs
= Fcons (Fcons (Qppid
,
6992 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6994 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6996 attrs
= Fcons (Fcons (Qthcount
,
6997 make_fixnum_or_float (pe
.cntThreads
)),
7004 CloseHandle (h_snapshot
);
7010 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7012 /* If we were denied a handle to the process, try again after
7013 enabling the SeDebugPrivilege in our process. */
7016 TOKEN_PRIVILEGES priv_current
;
7018 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
7020 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7022 restore_privilege (&priv_current
);
7028 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
7031 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
7032 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7034 buf
= xmalloc (blen
);
7035 result
= get_token_information (token
, TokenUser
,
7036 (LPVOID
)buf
, blen
, &needed
);
7039 memcpy (&user_token
, buf
, sizeof (user_token
));
7040 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
7042 euid
= get_rid (user_token
.User
.Sid
);
7043 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
7048 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
7051 strcpy (uname
, "unknown");
7055 ulength
= strlen (uname
);
7061 /* Determine a reasonable euid and gid values. */
7062 if (xstrcasecmp ("administrator", uname
) == 0)
7064 euid
= 500; /* well-known Administrator uid */
7065 egid
= 513; /* well-known None gid */
7069 /* Get group id and name. */
7070 result
= get_token_information (token
, TokenPrimaryGroup
,
7071 (LPVOID
)buf
, blen
, &needed
);
7072 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7074 buf
= xrealloc (buf
, blen
= needed
);
7075 result
= get_token_information (token
, TokenPrimaryGroup
,
7076 (LPVOID
)buf
, blen
, &needed
);
7080 memcpy (&group_token
, buf
, sizeof (group_token
));
7081 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
7083 egid
= get_rid (group_token
.PrimaryGroup
);
7084 dlength
= sizeof (domain
);
7086 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
7087 gname
, &glength
, NULL
, &dlength
,
7090 w32_add_to_cache (group_token
.PrimaryGroup
,
7094 strcpy (gname
, "None");
7098 glength
= strlen (gname
);
7106 if (!is_windows_9x ())
7108 /* We couldn't open the process token, presumably because of
7109 insufficient access rights. Assume this process is run
7111 strcpy (uname
, "SYSTEM");
7112 strcpy (gname
, "None");
7113 euid
= 18; /* SYSTEM */
7114 egid
= 513; /* None */
7115 glength
= strlen (gname
);
7116 ulength
= strlen (uname
);
7118 /* If we are running under Windows 9X, where security calls are
7119 not supported, we assume all processes are run by the current
7121 else if (GetUserName (uname
, &ulength
))
7123 if (xstrcasecmp ("administrator", uname
) == 0)
7128 strcpy (gname
, "None");
7129 glength
= strlen (gname
);
7130 ulength
= strlen (uname
);
7136 strcpy (uname
, "administrator");
7137 ulength
= strlen (uname
);
7138 strcpy (gname
, "None");
7139 glength
= strlen (gname
);
7142 CloseHandle (token
);
7145 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7146 tem
= make_unibyte_string (uname
, ulength
);
7147 attrs
= Fcons (Fcons (Quser
,
7148 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7150 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7151 tem
= make_unibyte_string (gname
, glength
);
7152 attrs
= Fcons (Fcons (Qgroup
,
7153 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7156 if (global_memory_status_ex (&memstex
))
7157 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7158 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7160 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7161 double, so we need to do this for it... */
7163 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7164 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7165 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7167 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7169 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7170 else if (global_memory_status (&memst
))
7171 totphys
= memst
.dwTotalPhys
/ 1024.0;
7174 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7177 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7179 attrs
= Fcons (Fcons (Qmajflt
,
7180 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7182 attrs
= Fcons (Fcons (Qvsize
,
7183 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7185 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7187 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7190 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7192 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7194 attrs
= Fcons (Fcons (Qmajflt
,
7195 make_fixnum_or_float (mem
.PageFaultCount
)),
7197 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7199 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7202 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7204 DWORD rss
= maxrss
/ 1024;
7206 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7208 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7211 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7213 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7214 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7215 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7216 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7217 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7218 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7221 /* FIXME: Retrieve command line by walking the PEB of the process. */
7224 CloseHandle (h_proc
);
7229 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7230 unsigned long long *totalswap
, unsigned long long *freeswap
)
7233 MEMORY_STATUS_EX memstex
;
7235 /* Use GlobalMemoryStatusEx if available, as it can report more than
7237 if (global_memory_status_ex (&memstex
))
7239 *totalram
= memstex
.ullTotalPhys
;
7240 *freeram
= memstex
.ullAvailPhys
;
7241 *totalswap
= memstex
.ullTotalPageFile
;
7242 *freeswap
= memstex
.ullAvailPageFile
;
7245 else if (global_memory_status (&memst
))
7247 *totalram
= memst
.dwTotalPhys
;
7248 *freeram
= memst
.dwAvailPhys
;
7249 *totalswap
= memst
.dwTotalPageFile
;
7250 *freeswap
= memst
.dwAvailPageFile
;
7258 /* Wrappers for winsock functions to map between our file descriptors
7259 and winsock's handles; also set h_errno for convenience.
7261 To allow Emacs to run on systems which don't have winsock support
7262 installed, we dynamically link to winsock on startup if present, and
7263 otherwise provide the minimum necessary functionality
7264 (eg. gethostname). */
7266 /* function pointers for relevant socket functions */
7267 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7268 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7269 int (PASCAL
*pfn_WSAGetLastError
) (void);
7270 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7271 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7272 WSANETWORKEVENTS
*NetworkEvents
);
7274 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7275 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7276 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7277 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7278 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7279 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7280 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7281 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7282 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7283 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7284 int (PASCAL
*pfn_WSACleanup
) (void);
7286 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7287 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7288 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7289 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7290 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7291 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7292 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7293 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7294 const char * optval
, int optlen
);
7295 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7296 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7298 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7299 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7300 struct sockaddr
* from
, int * fromlen
);
7301 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7302 const struct sockaddr
* to
, int tolen
);
7304 int (PASCAL
*pfn_getaddrinfo
) (const char *, const char *,
7305 const struct addrinfo
*, struct addrinfo
**);
7306 void (PASCAL
*pfn_freeaddrinfo
) (struct addrinfo
*);
7308 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7309 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7310 #ifndef HANDLE_FLAG_INHERIT
7311 #define HANDLE_FLAG_INHERIT 1
7315 static int winsock_inuse
;
7317 BOOL
term_winsock (void);
7322 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7324 release_listen_threads ();
7325 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7326 after WSAStartup returns successfully, but it seems reasonable
7327 to allow unloading winsock anyway in that case. */
7328 if (pfn_WSACleanup () == 0 ||
7329 pfn_WSAGetLastError () == WSAENETDOWN
)
7331 if (FreeLibrary (winsock_lib
))
7340 init_winsock (int load_now
)
7342 WSADATA winsockData
;
7344 if (winsock_lib
!= NULL
)
7347 pfn_SetHandleInformation
7348 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7349 "SetHandleInformation");
7351 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7353 if (winsock_lib
!= NULL
)
7355 /* dynamically link to socket functions */
7357 #define LOAD_PROC(fn) \
7358 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7361 LOAD_PROC (WSAStartup
);
7362 LOAD_PROC (WSASetLastError
);
7363 LOAD_PROC (WSAGetLastError
);
7364 LOAD_PROC (WSAEventSelect
);
7365 LOAD_PROC (WSAEnumNetworkEvents
);
7366 LOAD_PROC (WSACreateEvent
);
7367 LOAD_PROC (WSACloseEvent
);
7370 LOAD_PROC (connect
);
7371 LOAD_PROC (ioctlsocket
);
7374 LOAD_PROC (closesocket
);
7375 LOAD_PROC (shutdown
);
7378 LOAD_PROC (inet_addr
);
7379 LOAD_PROC (gethostname
);
7380 LOAD_PROC (gethostbyname
);
7381 LOAD_PROC (getservbyname
);
7382 LOAD_PROC (getpeername
);
7383 LOAD_PROC (WSACleanup
);
7384 LOAD_PROC (setsockopt
);
7386 LOAD_PROC (getsockname
);
7388 LOAD_PROC (recvfrom
);
7392 /* Try loading functions not available before XP. */
7393 pfn_getaddrinfo
= (void *) GetProcAddress (winsock_lib
, "getaddrinfo");
7394 pfn_freeaddrinfo
= (void *) GetProcAddress (winsock_lib
, "freeaddrinfo");
7395 /* Paranoia: these two functions should go together, so if one
7396 is absent, we cannot use the other. */
7397 if (pfn_getaddrinfo
== NULL
)
7398 pfn_freeaddrinfo
= NULL
;
7399 else if (pfn_freeaddrinfo
== NULL
)
7400 pfn_getaddrinfo
= NULL
;
7402 /* specify version 1.1 of winsock */
7403 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7405 if (winsockData
.wVersion
!= 0x101)
7410 /* Report that winsock exists and is usable, but leave
7411 socket functions disabled. I am assuming that calling
7412 WSAStartup does not require any network interaction,
7413 and in particular does not cause or require a dial-up
7414 connection to be established. */
7417 FreeLibrary (winsock_lib
);
7425 FreeLibrary (winsock_lib
);
7435 /* Function to map winsock error codes to errno codes for those errno
7436 code defined in errno.h (errno values not defined by errno.h are
7437 already in nt/inc/sys/socket.h). */
7444 if (winsock_lib
== NULL
)
7447 wsa_err
= pfn_WSAGetLastError ();
7451 case WSAEACCES
: errno
= EACCES
; break;
7452 case WSAEBADF
: errno
= EBADF
; break;
7453 case WSAEFAULT
: errno
= EFAULT
; break;
7454 case WSAEINTR
: errno
= EINTR
; break;
7455 case WSAEINVAL
: errno
= EINVAL
; break;
7456 case WSAEMFILE
: errno
= EMFILE
; break;
7457 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7458 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7459 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7460 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7461 default: errno
= wsa_err
; break;
7469 if (winsock_lib
!= NULL
)
7470 pfn_WSASetLastError (0);
7473 /* Extend strerror to handle the winsock-specific error codes. */
7477 } _wsa_errlist
[] = {
7478 {WSAEINTR
, "Interrupted function call"},
7479 {WSAEBADF
, "Bad file descriptor"},
7480 {WSAEACCES
, "Permission denied"},
7481 {WSAEFAULT
, "Bad address"},
7482 {WSAEINVAL
, "Invalid argument"},
7483 {WSAEMFILE
, "Too many open files"},
7485 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7486 {WSAEINPROGRESS
, "Operation now in progress"},
7487 {WSAEALREADY
, "Operation already in progress"},
7488 {WSAENOTSOCK
, "Socket operation on non-socket"},
7489 {WSAEDESTADDRREQ
, "Destination address required"},
7490 {WSAEMSGSIZE
, "Message too long"},
7491 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7492 {WSAENOPROTOOPT
, "Bad protocol option"},
7493 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7494 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7495 {WSAEOPNOTSUPP
, "Operation not supported"},
7496 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7497 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7498 {WSAEADDRINUSE
, "Address already in use"},
7499 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7500 {WSAENETDOWN
, "Network is down"},
7501 {WSAENETUNREACH
, "Network is unreachable"},
7502 {WSAENETRESET
, "Network dropped connection on reset"},
7503 {WSAECONNABORTED
, "Software caused connection abort"},
7504 {WSAECONNRESET
, "Connection reset by peer"},
7505 {WSAENOBUFS
, "No buffer space available"},
7506 {WSAEISCONN
, "Socket is already connected"},
7507 {WSAENOTCONN
, "Socket is not connected"},
7508 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7509 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7510 {WSAETIMEDOUT
, "Connection timed out"},
7511 {WSAECONNREFUSED
, "Connection refused"},
7512 {WSAELOOP
, "Network loop"}, /* not sure */
7513 {WSAENAMETOOLONG
, "Name is too long"},
7514 {WSAEHOSTDOWN
, "Host is down"},
7515 {WSAEHOSTUNREACH
, "No route to host"},
7516 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7517 {WSAEPROCLIM
, "Too many processes"},
7518 {WSAEUSERS
, "Too many users"}, /* not sure */
7519 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7520 {WSAESTALE
, "Data is stale"}, /* not sure */
7521 {WSAEREMOTE
, "Remote error"}, /* not sure */
7523 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7524 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7525 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7526 {WSAEDISCON
, "Graceful shutdown in progress"},
7528 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7529 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7530 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7531 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7532 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7533 {WSASYSCALLFAILURE
, "System call failure"},
7534 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7535 {WSATYPE_NOT_FOUND
, "Class type not found"},
7536 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7537 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7538 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7541 {WSAHOST_NOT_FOUND
, "Host not found"},
7542 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7543 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7544 {WSANO_DATA
, "Valid name, no data record of requested type"},
7550 sys_strerror (int error_no
)
7553 static char unknown_msg
[40];
7555 if (error_no
>= 0 && error_no
< sys_nerr
)
7556 return sys_errlist
[error_no
];
7558 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7559 if (_wsa_errlist
[i
].errnum
== error_no
)
7560 return (char *)_wsa_errlist
[i
].msg
;
7562 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7566 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7567 but I believe the method of keeping the socket handle separate (and
7568 insuring it is not inheritable) is the correct one. */
7570 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7572 static int socket_to_fd (SOCKET s
);
7575 sys_socket (int af
, int type
, int protocol
)
7579 if (winsock_lib
== NULL
)
7587 /* call the real socket function */
7588 s
= pfn_socket (af
, type
, protocol
);
7590 if (s
!= INVALID_SOCKET
)
7591 return socket_to_fd (s
);
7597 /* Convert a SOCKET to a file descriptor. */
7599 socket_to_fd (SOCKET s
)
7604 /* Although under NT 3.5 _open_osfhandle will accept a socket
7605 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7606 that does not work under NT 3.1. However, we can get the same
7607 effect by using a backdoor function to replace an existing
7608 descriptor handle with the one we want. */
7610 /* allocate a file descriptor (with appropriate flags) */
7611 fd
= _open ("NUL:", _O_RDWR
);
7614 /* Make a non-inheritable copy of the socket handle. Note
7615 that it is possible that sockets aren't actually kernel
7616 handles, which appears to be the case on Windows 9x when
7617 the MS Proxy winsock client is installed. */
7619 /* Apparently there is a bug in NT 3.51 with some service
7620 packs, which prevents using DuplicateHandle to make a
7621 socket handle non-inheritable (causes WSACleanup to
7622 hang). The work-around is to use SetHandleInformation
7623 instead if it is available and implemented. */
7624 if (pfn_SetHandleInformation
)
7626 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7630 HANDLE parent
= GetCurrentProcess ();
7631 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7633 if (DuplicateHandle (parent
,
7639 DUPLICATE_SAME_ACCESS
))
7641 /* It is possible that DuplicateHandle succeeds even
7642 though the socket wasn't really a kernel handle,
7643 because a real handle has the same value. So
7644 test whether the new handle really is a socket. */
7645 unsigned long nonblocking
= 0;
7646 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7648 pfn_closesocket (s
);
7653 CloseHandle (new_s
);
7658 eassert (fd
< MAXDESC
);
7659 fd_info
[fd
].hnd
= (HANDLE
) s
;
7661 /* set our own internal flags */
7662 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7668 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7670 /* attach child_process to fd_info */
7671 if (fd_info
[ fd
].cp
!= NULL
)
7673 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7677 fd_info
[ fd
].cp
= cp
;
7680 winsock_inuse
++; /* count open sockets */
7688 pfn_closesocket (s
);
7694 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7696 if (winsock_lib
== NULL
)
7699 return SOCKET_ERROR
;
7703 if (fd_info
[s
].flags
& FILE_SOCKET
)
7705 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7706 if (rc
== SOCKET_ERROR
)
7711 return SOCKET_ERROR
;
7715 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7717 if (winsock_lib
== NULL
)
7720 return SOCKET_ERROR
;
7724 if (fd_info
[s
].flags
& FILE_SOCKET
)
7726 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7727 if (rc
== SOCKET_ERROR
)
7730 /* If this is a non-blocking 'connect', set the bit in flags
7731 that will tell reader_thread to wait for connection
7732 before trying to read. */
7733 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7735 errno
= EINPROGRESS
; /* that's what process.c expects */
7736 fd_info
[s
].flags
|= FILE_CONNECT
;
7742 return SOCKET_ERROR
;
7746 sys_htons (u_short hostshort
)
7748 return (winsock_lib
!= NULL
) ?
7749 pfn_htons (hostshort
) : hostshort
;
7753 sys_ntohs (u_short netshort
)
7755 return (winsock_lib
!= NULL
) ?
7756 pfn_ntohs (netshort
) : netshort
;
7760 sys_inet_addr (const char * cp
)
7762 return (winsock_lib
!= NULL
) ?
7763 pfn_inet_addr (cp
) : INADDR_NONE
;
7767 sys_gethostname (char * name
, int namelen
)
7769 if (winsock_lib
!= NULL
)
7774 retval
= pfn_gethostname (name
, namelen
);
7775 if (retval
== SOCKET_ERROR
)
7780 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7781 return !GetComputerName (name
, (DWORD
*)&namelen
);
7784 return SOCKET_ERROR
;
7788 sys_gethostbyname (const char * name
)
7790 struct hostent
* host
;
7791 int h_err
= h_errno
;
7793 if (winsock_lib
== NULL
)
7795 h_errno
= NO_RECOVERY
;
7801 host
= pfn_gethostbyname (name
);
7813 sys_getservbyname (const char * name
, const char * proto
)
7815 struct servent
* serv
;
7817 if (winsock_lib
== NULL
)
7824 serv
= pfn_getservbyname (name
, proto
);
7831 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7833 if (winsock_lib
== NULL
)
7836 return SOCKET_ERROR
;
7840 if (fd_info
[s
].flags
& FILE_SOCKET
)
7842 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7843 if (rc
== SOCKET_ERROR
)
7848 return SOCKET_ERROR
;
7852 sys_getaddrinfo (const char *node
, const char *service
,
7853 const struct addrinfo
*hints
, struct addrinfo
**res
)
7857 if (winsock_lib
== NULL
)
7860 return SOCKET_ERROR
;
7864 if (pfn_getaddrinfo
)
7865 rc
= pfn_getaddrinfo (node
, service
, hints
, res
);
7869 struct hostent
*host_info
;
7870 struct gai_storage
{
7871 struct addrinfo addrinfo
;
7872 struct sockaddr_in sockaddr_in
;
7875 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7876 if (hints
&& hints
->ai_flags
!= 0)
7878 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7880 return WSAHOST_NOT_FOUND
;
7884 const char *protocol
=
7885 (hints
&& hints
->ai_socktype
== SOCK_DGRAM
) ? "udp" : "tcp";
7886 struct servent
*srv
= sys_getservbyname (service
, protocol
);
7890 else if (*service
>= '0' && *service
<= '9')
7894 port
= strtoul (service
, &endp
, 10);
7895 if (*endp
|| port
> 65536)
7896 return WSAHOST_NOT_FOUND
;
7897 port
= sys_htons ((unsigned short) port
);
7900 return WSAHOST_NOT_FOUND
;
7903 gai_storage
= xzalloc (sizeof *gai_storage
);
7904 gai_storage
->sockaddr_in
.sin_port
= port
;
7905 host_info
= sys_gethostbyname (node
);
7908 memcpy (&gai_storage
->sockaddr_in
.sin_addr
,
7909 host_info
->h_addr
, host_info
->h_length
);
7910 gai_storage
->sockaddr_in
.sin_family
= host_info
->h_addrtype
;
7914 /* Attempt to interpret host as numeric inet address. */
7915 unsigned long numeric_addr
= sys_inet_addr (node
);
7917 if (numeric_addr
== -1)
7920 return WSAHOST_NOT_FOUND
;
7923 memcpy (&gai_storage
->sockaddr_in
.sin_addr
, &numeric_addr
,
7924 sizeof (gai_storage
->sockaddr_in
.sin_addr
));
7925 gai_storage
->sockaddr_in
.sin_family
= (hints
) ? hints
->ai_family
: 0;
7928 gai_storage
->addrinfo
.ai_addr
=
7929 (struct sockaddr
*)&gai_storage
->sockaddr_in
;
7930 gai_storage
->addrinfo
.ai_addrlen
= sizeof (gai_storage
->sockaddr_in
);
7931 gai_storage
->addrinfo
.ai_protocol
= (hints
) ? hints
->ai_protocol
: 0;
7932 gai_storage
->addrinfo
.ai_socktype
= (hints
) ? hints
->ai_socktype
: 0;
7933 gai_storage
->addrinfo
.ai_family
= gai_storage
->sockaddr_in
.sin_family
;
7934 gai_storage
->addrinfo
.ai_next
= NULL
;
7936 *res
= &gai_storage
->addrinfo
;
7944 sys_freeaddrinfo (struct addrinfo
*ai
)
7946 if (winsock_lib
== NULL
)
7953 if (pfn_freeaddrinfo
)
7954 pfn_freeaddrinfo (ai
);
7957 eassert (ai
->ai_next
== NULL
);
7963 sys_shutdown (int s
, int how
)
7965 if (winsock_lib
== NULL
)
7968 return SOCKET_ERROR
;
7972 if (fd_info
[s
].flags
& FILE_SOCKET
)
7974 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7975 if (rc
== SOCKET_ERROR
)
7980 return SOCKET_ERROR
;
7984 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7986 if (winsock_lib
== NULL
)
7989 return SOCKET_ERROR
;
7993 if (fd_info
[s
].flags
& FILE_SOCKET
)
7995 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7996 (const char *)optval
, optlen
);
7997 if (rc
== SOCKET_ERROR
)
8002 return SOCKET_ERROR
;
8006 sys_listen (int s
, int backlog
)
8008 if (winsock_lib
== NULL
)
8011 return SOCKET_ERROR
;
8015 if (fd_info
[s
].flags
& FILE_SOCKET
)
8017 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
8018 if (rc
== SOCKET_ERROR
)
8021 fd_info
[s
].flags
|= FILE_LISTEN
;
8025 return SOCKET_ERROR
;
8029 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
8031 if (winsock_lib
== NULL
)
8034 return SOCKET_ERROR
;
8038 if (fd_info
[s
].flags
& FILE_SOCKET
)
8040 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
8041 if (rc
== SOCKET_ERROR
)
8046 return SOCKET_ERROR
;
8050 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
8052 if (winsock_lib
== NULL
)
8059 if (fd_info
[s
].flags
& FILE_LISTEN
)
8061 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
8063 if (t
== INVALID_SOCKET
)
8066 fd
= socket_to_fd (t
);
8070 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8071 ResetEvent (fd_info
[s
].cp
->char_avail
);
8080 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
8081 struct sockaddr
* from
, int * fromlen
)
8083 if (winsock_lib
== NULL
)
8086 return SOCKET_ERROR
;
8090 if (fd_info
[s
].flags
& FILE_SOCKET
)
8092 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
8093 if (rc
== SOCKET_ERROR
)
8098 return SOCKET_ERROR
;
8102 sys_sendto (int s
, const char * buf
, int len
, int flags
,
8103 const struct sockaddr
* to
, int tolen
)
8105 if (winsock_lib
== NULL
)
8108 return SOCKET_ERROR
;
8112 if (fd_info
[s
].flags
& FILE_SOCKET
)
8114 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
8115 if (rc
== SOCKET_ERROR
)
8120 return SOCKET_ERROR
;
8123 /* Windows does not have an fcntl function. Provide an implementation
8124 good enough for Emacs. */
8126 fcntl (int s
, int cmd
, int options
)
8128 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8129 invoked in a context where fd1 is closed and all descriptors less
8130 than fd1 are open, so sys_dup is an adequate implementation. */
8131 if (cmd
== F_DUPFD_CLOEXEC
)
8135 if (fd_info
[s
].flags
& FILE_SOCKET
)
8137 if (winsock_lib
== NULL
)
8143 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8145 unsigned long nblock
= 1;
8146 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
8147 if (rc
== SOCKET_ERROR
)
8149 /* Keep track of the fact that we set this to non-blocking. */
8150 fd_info
[s
].flags
|= FILE_NDELAY
;
8156 return SOCKET_ERROR
;
8159 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
8160 == (FILE_PIPE
| FILE_WRITE
))
8162 /* Force our writes to pipes be non-blocking. */
8163 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8165 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
8166 DWORD pipe_mode
= PIPE_NOWAIT
;
8168 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
8170 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8171 return SOCKET_ERROR
;
8173 fd_info
[s
].flags
|= FILE_NDELAY
;
8179 return SOCKET_ERROR
;
8183 return SOCKET_ERROR
;
8187 /* Shadow main io functions: we need to handle pipes and sockets more
8201 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
8203 child_process
* cp
= fd_info
[fd
].cp
;
8205 fd_info
[fd
].cp
= NULL
;
8207 if (CHILD_ACTIVE (cp
))
8209 /* if last descriptor to active child_process then cleanup */
8211 for (i
= 0; i
< MAXDESC
; i
++)
8215 if (fd_info
[i
].cp
== cp
)
8220 if (fd_info
[fd
].flags
& FILE_SOCKET
)
8222 if (winsock_lib
== NULL
) emacs_abort ();
8224 pfn_shutdown (SOCK_HANDLE (fd
), 2);
8225 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
8227 winsock_inuse
--; /* count open sockets */
8229 /* If the process handle is NULL, it's either a socket
8230 or serial connection, or a subprocess that was
8231 already reaped by reap_subprocess, but whose
8232 resources were not yet freed, because its output was
8233 not fully read yet by the time it was reaped. (This
8234 usually happens with async subprocesses whose output
8235 is being read by Emacs.) Otherwise, this process was
8236 not reaped yet, so we set its FD to a negative value
8237 to make sure sys_select will eventually get to
8238 calling the SIGCHLD handler for it, which will then
8239 invoke waitpid and reap_subprocess. */
8240 if (cp
->procinfo
.hProcess
== NULL
)
8248 if (fd
>= 0 && fd
< MAXDESC
)
8249 fd_info
[fd
].flags
= 0;
8251 /* Note that sockets do not need special treatment here (at least on
8252 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8253 closesocket is equivalent to CloseHandle, which is to be expected
8254 because socket handles are fully fledged kernel handles. */
8266 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8268 /* duplicate our internal info as well */
8269 fd_info
[new_fd
] = fd_info
[fd
];
8275 sys_dup2 (int src
, int dst
)
8279 if (dst
< 0 || dst
>= MAXDESC
)
8285 /* MS _dup2 seems to have weird side effect when invoked with 2
8286 identical arguments: an attempt to fclose the corresponding stdio
8287 stream after that hangs (we do close standard streams in
8288 init_ntproc). Attempt to avoid that by not calling _dup2 that
8289 way: if SRC is valid, we know that dup2 should be a no-op, so do
8290 nothing and return DST. */
8293 if ((HANDLE
)_get_osfhandle (src
) == INVALID_HANDLE_VALUE
)
8301 /* Make sure we close the destination first if it's a pipe or socket. */
8302 if (fd_info
[dst
].flags
!= 0)
8305 rc
= _dup2 (src
, dst
);
8308 /* Duplicate our internal info as well. */
8309 fd_info
[dst
] = fd_info
[src
];
8311 return rc
== 0 ? dst
: rc
;
8315 pipe2 (int * phandles
, int pipe2_flags
)
8319 unsigned pipe_size
= 0;
8321 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8323 /* Allow Lisp to override the default buffer size of the pipe. */
8324 if (w32_pipe_buffer_size
> 0 && w32_pipe_buffer_size
< UINT_MAX
)
8325 pipe_size
= w32_pipe_buffer_size
;
8327 /* make pipe handles non-inheritable; when we spawn a child, we
8328 replace the relevant handle with an inheritable one. Also put
8329 pipes into binary mode; we will do text mode translation ourselves
8331 rc
= _pipe (phandles
, pipe_size
, _O_NOINHERIT
| _O_BINARY
);
8335 /* Protect against overflow, since Windows can open more handles than
8336 our fd_info array has room for. */
8337 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8339 _close (phandles
[0]);
8340 _close (phandles
[1]);
8346 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8347 fd_info
[phandles
[0]].flags
= flags
;
8349 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8350 fd_info
[phandles
[1]].flags
= flags
;
8357 /* Function to do blocking read of one byte, needed to implement
8358 select. It is only allowed on communication ports, sockets, or
8361 _sys_read_ahead (int fd
)
8366 if (fd
< 0 || fd
>= MAXDESC
)
8367 return STATUS_READ_ERROR
;
8369 cp
= fd_info
[fd
].cp
;
8371 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8372 return STATUS_READ_ERROR
;
8374 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8375 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8377 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8381 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8382 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8383 cp
->status
= STATUS_READ_IN_PROGRESS
;
8385 if (fd_info
[fd
].flags
& FILE_PIPE
)
8387 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8389 /* Give subprocess time to buffer some more output for us before
8390 reporting that input is available; we need this because Windows 95
8391 connects DOS programs to pipes by making the pipe appear to be
8392 the normal console stdout - as a result most DOS programs will
8393 write to stdout without buffering, ie. one character at a
8394 time. Even some W32 programs do this - "dir" in a command
8395 shell on NT is very slow if we don't do this. */
8398 int wait
= w32_pipe_read_delay
;
8404 /* Yield remainder of our time slice, effectively giving a
8405 temporary priority boost to the child process. */
8409 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8411 HANDLE hnd
= fd_info
[fd
].hnd
;
8412 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8415 /* Configure timeouts for blocking read. */
8416 if (!GetCommTimeouts (hnd
, &ct
))
8418 cp
->status
= STATUS_READ_ERROR
;
8419 return STATUS_READ_ERROR
;
8421 ct
.ReadIntervalTimeout
= 0;
8422 ct
.ReadTotalTimeoutMultiplier
= 0;
8423 ct
.ReadTotalTimeoutConstant
= 0;
8424 if (!SetCommTimeouts (hnd
, &ct
))
8426 cp
->status
= STATUS_READ_ERROR
;
8427 return STATUS_READ_ERROR
;
8430 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8432 if (GetLastError () != ERROR_IO_PENDING
)
8434 cp
->status
= STATUS_READ_ERROR
;
8435 return STATUS_READ_ERROR
;
8437 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8439 cp
->status
= STATUS_READ_ERROR
;
8440 return STATUS_READ_ERROR
;
8444 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8446 unsigned long nblock
= 0;
8447 /* We always want this to block, so temporarily disable NDELAY. */
8448 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8449 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8451 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8453 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8456 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8460 if (rc
== sizeof (char))
8461 cp
->status
= STATUS_READ_SUCCEEDED
;
8463 cp
->status
= STATUS_READ_FAILED
;
8469 _sys_wait_accept (int fd
)
8475 if (fd
< 0 || fd
>= MAXDESC
)
8476 return STATUS_READ_ERROR
;
8478 cp
= fd_info
[fd
].cp
;
8480 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8481 return STATUS_READ_ERROR
;
8483 cp
->status
= STATUS_READ_FAILED
;
8485 hEv
= pfn_WSACreateEvent ();
8486 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8487 if (rc
!= SOCKET_ERROR
)
8490 rc
= WaitForSingleObject (hEv
, 500);
8492 } while (rc
== WAIT_TIMEOUT
8493 && cp
->status
!= STATUS_READ_ERROR
8495 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8496 if (rc
== WAIT_OBJECT_0
)
8497 cp
->status
= STATUS_READ_SUCCEEDED
;
8499 pfn_WSACloseEvent (hEv
);
8505 _sys_wait_connect (int fd
)
8511 if (fd
< 0 || fd
>= MAXDESC
)
8512 return STATUS_READ_ERROR
;
8514 cp
= fd_info
[fd
].cp
;
8515 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8516 return STATUS_READ_ERROR
;
8518 cp
->status
= STATUS_READ_FAILED
;
8520 hEv
= pfn_WSACreateEvent ();
8521 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8522 if (rc
!= SOCKET_ERROR
)
8525 rc
= WaitForSingleObject (hEv
, 500);
8527 } while (rc
== WAIT_TIMEOUT
8528 && cp
->status
!= STATUS_READ_ERROR
8530 if (rc
== WAIT_OBJECT_0
)
8532 /* We've got an event, but it could be a successful
8533 connection, or it could be a failure. Find out
8535 WSANETWORKEVENTS events
;
8537 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8538 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8539 && events
.iErrorCode
[FD_CONNECT_BIT
])
8541 cp
->status
= STATUS_CONNECT_FAILED
;
8542 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8546 cp
->status
= STATUS_READ_SUCCEEDED
;
8550 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8553 pfn_WSACloseEvent (hEv
);
8559 sys_read (int fd
, char * buffer
, unsigned int count
)
8564 char * orig_buffer
= buffer
;
8572 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8574 child_process
*cp
= fd_info
[fd
].cp
;
8576 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8584 /* re-read CR carried over from last read */
8585 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8587 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8591 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8594 /* presence of a child_process structure means we are operating in
8595 non-blocking mode - otherwise we just call _read directly.
8596 Note that the child_process structure might be missing because
8597 reap_subprocess has been called; in this case the pipe is
8598 already broken, so calling _read on it is okay. */
8601 int current_status
= cp
->status
;
8603 switch (current_status
)
8605 case STATUS_READ_FAILED
:
8606 case STATUS_READ_ERROR
:
8607 /* report normal EOF if nothing in buffer */
8609 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8612 case STATUS_READ_READY
:
8613 case STATUS_READ_IN_PROGRESS
:
8615 /* This happens all the time during GnuTLS handshake
8616 with the remote, evidently because GnuTLS waits for
8617 the read to complete by retrying the read operation
8618 upon EAGAIN. So I'm disabling the DebPrint to avoid
8619 wasting cycles on something that is not a real
8620 problem. Enable if you need to debug something that
8622 DebPrint (("sys_read called when read is in progress %d\n",
8625 errno
= EWOULDBLOCK
;
8628 case STATUS_READ_SUCCEEDED
:
8629 /* consume read-ahead char */
8630 *buffer
++ = cp
->chr
;
8633 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8634 ResetEvent (cp
->char_avail
);
8636 case STATUS_READ_ACKNOWLEDGED
:
8637 case STATUS_CONNECT_FAILED
:
8641 DebPrint (("sys_read: bad status %d\n", current_status
));
8646 if (fd_info
[fd
].flags
& FILE_PIPE
)
8648 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8649 to_read
= min (waiting
, (DWORD
) count
);
8652 nchars
+= _read (fd
, buffer
, to_read
);
8654 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8656 HANDLE hnd
= fd_info
[fd
].hnd
;
8657 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8663 /* Configure timeouts for non-blocking read. */
8664 if (!GetCommTimeouts (hnd
, &ct
))
8669 ct
.ReadIntervalTimeout
= MAXDWORD
;
8670 ct
.ReadTotalTimeoutMultiplier
= 0;
8671 ct
.ReadTotalTimeoutConstant
= 0;
8672 if (!SetCommTimeouts (hnd
, &ct
))
8678 if (!ResetEvent (ovl
->hEvent
))
8683 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8685 if (GetLastError () != ERROR_IO_PENDING
)
8690 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8699 else /* FILE_SOCKET */
8701 if (winsock_lib
== NULL
) emacs_abort ();
8703 /* When a non-blocking 'connect' call fails,
8704 wait_reading_process_output detects this by calling
8705 'getpeername', and then attempts to obtain the connection
8706 error code by trying to read 1 byte from the socket. If
8707 we try to serve that read by calling 'recv' below, the
8708 error we get is a generic WSAENOTCONN, not the actual
8709 connection error. So instead, we use the actual error
8710 code stashed by '_sys_wait_connect' in cp->errcode.
8711 Alternatively, we could have used 'getsockopt', like on
8712 GNU/Linux, but: (a) I have no idea whether the winsock
8713 version could hang, as it does "on some systems" (see the
8714 comment in process.c); and (b) 'getsockopt' on Windows is
8715 documented to clear the socket error for the entire
8716 process, which I'm not sure is TRT; FIXME. */
8717 if (current_status
== STATUS_CONNECT_FAILED
8718 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8719 && cp
->errcode
!= 0)
8721 pfn_WSASetLastError (cp
->errcode
);
8725 /* Do the equivalent of a non-blocking read. */
8726 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8727 if (waiting
== 0 && nchars
== 0)
8729 errno
= EWOULDBLOCK
;
8735 /* always use binary mode for sockets */
8736 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8737 if (res
== SOCKET_ERROR
)
8740 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8741 errno
, SOCK_HANDLE (fd
)));
8750 int nread
= _read (fd
, buffer
, count
);
8753 else if (nchars
== 0)
8758 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8759 /* Perform text mode translation if required. */
8760 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8762 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8763 /* If buffer contains only CR, return that. To be absolutely
8764 sure we should attempt to read the next char, but in
8765 practice a CR to be followed by LF would not appear by
8766 itself in the buffer. */
8767 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8769 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8775 nchars
= _read (fd
, buffer
, count
);
8780 /* From w32xfns.c */
8781 extern HANDLE interrupt_handle
;
8784 sys_write (int fd
, const void * buffer
, unsigned int count
)
8795 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8797 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8803 /* Perform text mode translation if required. */
8804 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8807 const unsigned char * src
= buffer
;
8808 unsigned char * dst
;
8811 SAFE_NALLOCA (tmpbuf
, 2, count
);
8812 dst
= (unsigned char *)tmpbuf
;
8816 unsigned char *next
;
8817 /* Copy next line or remaining bytes. */
8818 next
= _memccpy (dst
, src
, '\n', nbytes
);
8821 /* Copied one line ending with '\n'. */
8822 int copied
= next
- dst
;
8825 /* Insert '\r' before '\n'. */
8832 /* Copied remaining partial line -> now finished. */
8839 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8841 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8842 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8843 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8846 /* This is async (a.k.a. "overlapped") I/O, so the return value
8847 of FALSE from WriteFile means either an error or the output
8848 will be completed asynchronously (ERROR_IO_PENDING). */
8849 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8851 if (GetLastError () != ERROR_IO_PENDING
)
8858 /* Wait for the write to complete, and watch C-g while
8860 if (detect_input_pending ())
8861 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8862 INFINITE
, QS_ALLINPUT
);
8864 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8868 /* User pressed C-g, cancel write, then leave.
8869 Don't bother cleaning up as we may only get stuck
8870 in buggy drivers. */
8871 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8873 errno
= EIO
; /* Why not EINTR? */
8876 case WAIT_OBJECT_0
+ 1:
8877 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8887 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8889 unsigned long nblock
= 0;
8890 if (winsock_lib
== NULL
) emacs_abort ();
8892 child_process
*cp
= fd_info
[fd
].cp
;
8894 /* If this is a non-blocking socket whose connection is in
8895 progress or terminated with an error already, return the
8896 proper error code to the caller. */
8897 if (cp
!= NULL
&& (fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8899 /* In case connection is in progress, ENOTCONN that would
8900 result from calling pfn_send is not what callers expect. */
8901 if (cp
->status
!= STATUS_CONNECT_FAILED
)
8903 errno
= EWOULDBLOCK
;
8906 /* In case connection failed, use the actual error code
8907 stashed by '_sys_wait_connect' in cp->errcode. */
8908 else if (cp
->errcode
!= 0)
8910 pfn_WSASetLastError (cp
->errcode
);
8916 /* TODO: implement select() properly so non-blocking I/O works. */
8917 /* For now, make sure the write blocks. */
8918 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8919 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8921 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8923 if (nchars
== SOCKET_ERROR
)
8926 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8927 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8930 /* Set the socket back to non-blocking if it was before,
8931 for other operations that support it. */
8932 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8935 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8940 /* Some networked filesystems don't like too large writes, so
8941 break them into smaller chunks. See the Comments section of
8942 the MSDN documentation of WriteFile for details behind the
8943 choice of the value of CHUNK below. See also the thread
8944 http://thread.gmane.org/gmane.comp.version-control.git/145294
8945 in the git mailing list. */
8946 const unsigned char *p
= buffer
;
8947 const bool is_pipe
= (fd
< MAXDESC
8948 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8949 == (FILE_PIPE
| FILE_NDELAY
)));
8950 /* Some programs, notably Node.js's node.exe, seem to never
8951 completely empty the pipe, so writing more than the size of
8952 the pipe's buffer always returns ENOSPC, and we loop forever
8953 between send_process and here. As a workaround, write no
8954 more than the pipe's buffer can hold. */
8955 DWORD pipe_buffer_size
;
8958 if (!GetNamedPipeInfo ((HANDLE
)_get_osfhandle (fd
),
8959 NULL
, &pipe_buffer_size
, NULL
, NULL
))
8961 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8962 pipe_buffer_size
= 4096;
8965 const unsigned chunk
= is_pipe
? pipe_buffer_size
: 30 * 1024 * 1024;
8971 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8972 int n
= _write (fd
, p
, this_chunk
);
8978 /* When there's no buffer space in a pipe that is in the
8979 non-blocking mode, _write returns ENOSPC. We return
8980 EAGAIN instead, which should trigger the logic in
8981 send_process that enters waiting loop and calls
8982 wait_reading_process_output to allow process input to
8983 be accepted during the wait. Those calls to
8984 wait_reading_process_output allow sys_select to
8985 notice when process input becomes available, thus
8986 avoiding deadlock whereby each side of the pipe is
8987 blocked on write, waiting for the other party to read
8988 its end of the pipe. */
8989 if (errno
== ENOSPC
&& is_pipe
)
8995 else if (n
< this_chunk
)
9007 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
9009 /* Return information about network interface IFNAME, or about all
9010 interfaces (if IFNAME is nil). */
9012 network_interface_get_info (Lisp_Object ifname
)
9014 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
9015 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
9016 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
9017 Lisp_Object res
= Qnil
;
9019 if (retval
== ERROR_BUFFER_OVERFLOW
)
9021 ainfo
= xrealloc (ainfo
, ainfo_len
);
9022 retval
= get_adapters_info (ainfo
, &ainfo_len
);
9025 if (retval
== ERROR_SUCCESS
)
9027 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
9028 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
9030 struct sockaddr_in sa
;
9032 /* For the below, we need some winsock functions, so make sure
9033 the winsock DLL is loaded. If we cannot successfully load
9034 it, they will have no use of the information we provide,
9036 if (!winsock_lib
&& !init_winsock (1))
9039 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
9041 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
9043 /* Present Unix-compatible interface names, instead of the
9044 Windows names, which are really GUIDs not readable by
9046 static const char *ifmt
[] = {
9047 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9062 switch (adapter
->Type
)
9064 case MIB_IF_TYPE_ETHERNET
:
9065 /* Windows before Vista reports wireless adapters as
9066 Ethernet. Work around by looking at the Description
9068 if (strstr (adapter
->Description
, "Wireless "))
9071 if_num
= wlan_count
++;
9075 ifmt_idx
= ETHERNET
;
9076 if_num
= eth_count
++;
9079 case MIB_IF_TYPE_TOKENRING
:
9080 ifmt_idx
= TOKENRING
;
9081 if_num
= tr_count
++;
9083 case MIB_IF_TYPE_FDDI
:
9085 if_num
= fddi_count
++;
9087 case MIB_IF_TYPE_PPP
:
9089 if_num
= ppp_count
++;
9091 case MIB_IF_TYPE_SLIP
:
9093 if_num
= sl_count
++;
9095 case IF_TYPE_IEEE80211
:
9097 if_num
= wlan_count
++;
9099 case MIB_IF_TYPE_LOOPBACK
:
9102 ifmt_idx
= LOOPBACK
;
9103 if_num
= lo_count
++;
9109 ifmt_idx
= OTHER_IF
;
9110 if_num
= ifx_count
++;
9113 if (ifmt_idx
== NONE
)
9115 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
9117 sa
.sin_family
= AF_INET
;
9118 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
9119 if (ip_addr
== INADDR_NONE
)
9121 /* Bogus address, skip this interface. */
9124 sa
.sin_addr
.s_addr
= ip_addr
;
9127 res
= Fcons (Fcons (build_string (namebuf
),
9128 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9129 sizeof (struct sockaddr
))),
9131 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
9133 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
9134 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
9135 Lisp_Object flags
= Qnil
;
9139 /* Flags. We guess most of them by type, since the
9140 Windows flags are different and hard to get by. */
9141 flags
= Fcons (intern ("up"), flags
);
9142 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
9144 flags
= Fcons (intern ("broadcast"), flags
);
9145 flags
= Fcons (intern ("multicast"), flags
);
9147 flags
= Fcons (intern ("running"), flags
);
9148 if (ifmt_idx
== PPP
)
9150 flags
= Fcons (intern ("pointopoint"), flags
);
9151 flags
= Fcons (intern ("noarp"), flags
);
9153 if (adapter
->HaveWins
)
9154 flags
= Fcons (intern ("WINS"), flags
);
9155 if (adapter
->DhcpEnabled
)
9156 flags
= Fcons (intern ("dynamic"), flags
);
9158 res
= Fcons (flags
, res
);
9160 /* Hardware address and its family. */
9161 for (n
= 0; n
< adapter
->AddressLength
; n
++)
9162 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
9163 /* Windows does not support AF_LINK or AF_PACKET family
9164 of addresses. Use an arbitrary family number that is
9165 identical to what GNU/Linux returns. */
9166 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
9169 sa
.sin_family
= AF_INET
;
9170 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
9171 if (net_mask
!= INADDR_NONE
)
9173 sa
.sin_addr
.s_addr
= net_mask
;
9175 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9176 sizeof (struct sockaddr
)),
9180 res
= Fcons (Qnil
, res
);
9182 sa
.sin_family
= AF_INET
;
9183 if (ip_addr
!= INADDR_NONE
)
9185 /* Broadcast address is only reported by
9186 GetAdaptersAddresses, which is of limited
9187 availability. Generate it on our own. */
9188 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
9190 sa
.sin_addr
.s_addr
= bcast_addr
;
9192 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9193 sizeof (struct sockaddr
)),
9197 sa
.sin_addr
.s_addr
= ip_addr
;
9199 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9200 sizeof (struct sockaddr
)),
9204 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
9207 /* GetAdaptersInfo is documented to not report loopback
9208 interfaces, so we generate one out of thin air. */
9211 sa
.sin_family
= AF_INET
;
9215 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9216 res
= Fcons (Fcons (build_string ("lo"),
9217 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9218 sizeof (struct sockaddr
))),
9221 else if (strcmp (SSDATA (ifname
), "lo") == 0)
9223 res
= Fcons (Fcons (intern ("running"),
9224 Fcons (intern ("loopback"),
9225 Fcons (intern ("up"), Qnil
))), Qnil
);
9226 /* 772 is what 3 different GNU/Linux systems report for
9227 the loopback interface. */
9228 res
= Fcons (Fcons (make_number (772),
9229 Fmake_vector (make_number (6),
9232 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
9233 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9234 sizeof (struct sockaddr
)),
9236 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.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 ("127.0.0.1");
9241 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9242 sizeof (struct sockaddr
)),
9255 network_interface_list (void)
9257 return network_interface_get_info (Qnil
);
9261 network_interface_info (Lisp_Object ifname
)
9263 CHECK_STRING (ifname
);
9264 return network_interface_get_info (ifname
);
9268 /* The Windows CRT functions are "optimized for speed", so they don't
9269 check for timezone and DST changes if they were last called less
9270 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9271 all Emacs features that repeatedly call time functions (e.g.,
9272 display-time) are in real danger of missing timezone and DST
9273 changes. Calling tzset before each localtime call fixes that. */
9275 sys_localtime (const time_t *t
)
9278 return localtime (t
);
9283 /* Try loading LIBRARY_ID from the file(s) specified in
9284 Vdynamic_library_alist. If the library is loaded successfully,
9285 return the handle of the DLL, and record the filename in the
9286 property :loaded-from of LIBRARY_ID. If the library could not be
9287 found, or when it was already loaded (because the handle is not
9288 recorded anywhere, and so is lost after use), return NULL.
9290 We could also save the handle in :loaded-from, but currently
9291 there's no use case for it. */
9293 w32_delayed_load (Lisp_Object library_id
)
9295 HMODULE dll_handle
= NULL
;
9297 CHECK_SYMBOL (library_id
);
9299 if (CONSP (Vdynamic_library_alist
)
9300 && NILP (Fassq (library_id
, Vlibrary_cache
)))
9302 Lisp_Object found
= Qnil
;
9303 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
9306 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
9308 Lisp_Object dll
= XCAR (dlls
);
9309 char name
[MAX_UTF8_PATH
];
9313 dll
= ENCODE_FILE (dll
);
9314 if (w32_unicode_filenames
)
9316 wchar_t name_w
[MAX_PATH
];
9318 filename_to_utf16 (SSDATA (dll
), name_w
);
9319 dll_handle
= LoadLibraryW (name_w
);
9322 res
= GetModuleFileNameW (dll_handle
, name_w
,
9325 filename_from_utf16 (name_w
, name
);
9330 char name_a
[MAX_PATH
];
9332 filename_to_ansi (SSDATA (dll
), name_a
);
9333 dll_handle
= LoadLibraryA (name_a
);
9336 res
= GetModuleFileNameA (dll_handle
, name_a
,
9339 filename_from_ansi (name_a
, name
);
9344 ptrdiff_t len
= strlen (name
);
9347 /* Possibly truncated */
9348 ? make_specified_string (name
, -1, len
, 1)
9350 /* This prevents thread start and end notifications
9351 from being sent to the DLL, for every thread we
9352 start. We don't need those notifications because
9353 threads we create never use any of these DLLs, only
9354 the main thread uses them. This is supposed to
9355 speed up thread creation. */
9356 DisableThreadLibraryCalls (dll_handle
);
9361 Fput (library_id
, QCloaded_from
, found
);
9369 check_windows_init_file (void)
9371 /* A common indication that Emacs is not installed properly is when
9372 it cannot find the Windows installation file. If this file does
9373 not exist in the expected place, tell the user. */
9375 if (!noninteractive
&& !inhibit_window_system
9376 /* Vload_path is not yet initialized when we are loading
9378 && NILP (Vpurify_flag
))
9380 Lisp_Object init_file
;
9383 /* Implementation note: this function runs early during Emacs
9384 startup, before startup.el is run. So Vload_path is still in
9385 its initial unibyte form, but it holds UTF-8 encoded file
9386 names, since init_callproc was already called. So we do not
9387 need to ENCODE_FILE here, but we do need to convert the file
9388 names from UTF-8 to ANSI. */
9389 init_file
= build_string ("term/w32-win");
9390 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9393 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9394 char *init_file_name
= SSDATA (init_file
);
9395 char *load_path
= SSDATA (load_path_print
);
9396 char *buffer
= alloca (1024
9397 + strlen (init_file_name
)
9398 + strlen (load_path
));
9403 "The Emacs Windows initialization file \"%s.el\" "
9404 "could not be found in your Emacs installation. "
9405 "Emacs checked the following directories for this file:\n"
9407 "When Emacs cannot find this file, it usually means that it "
9408 "was not installed properly, or its distribution file was "
9409 "not unpacked properly.\nSee the README.W32 file in the "
9410 "top-level Emacs directory for more information.",
9411 init_file_name
, load_path
);
9412 needed
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
,
9413 buffer
, -1, NULL
, 0);
9416 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9418 pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, buffer
,
9420 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9421 NULL
, 0, NULL
, NULL
);
9424 char *msg_a
= alloca (needed
+ 1);
9426 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9433 "Emacs Abort Dialog",
9434 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9435 /* Use the low-level system abort. */
9446 term_ntproc (int ignored
)
9452 /* shutdown the socket interface if necessary */
9459 init_ntproc (int dumping
)
9461 sigset_t initial_mask
= 0;
9463 /* Initialize the socket interface now if available and requested by
9464 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9465 delayed until open-network-stream is called (w32-has-winsock can
9466 also be used to dynamically load or reload winsock).
9468 Conveniently, init_environment is called before us, so
9469 PRELOAD_WINSOCK can be set in the registry. */
9471 /* Always initialize this correctly. */
9474 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9475 init_winsock (TRUE
);
9477 /* Initial preparation for subprocess support: replace our standard
9478 handles with non-inheritable versions. */
9481 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9482 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9483 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9485 parent
= GetCurrentProcess ();
9487 /* ignore errors when duplicating and closing; typically the
9488 handles will be invalid when running as a gui program. */
9489 DuplicateHandle (parent
,
9490 GetStdHandle (STD_INPUT_HANDLE
),
9495 DUPLICATE_SAME_ACCESS
);
9497 DuplicateHandle (parent
,
9498 GetStdHandle (STD_OUTPUT_HANDLE
),
9503 DUPLICATE_SAME_ACCESS
);
9505 DuplicateHandle (parent
,
9506 GetStdHandle (STD_ERROR_HANDLE
),
9511 DUPLICATE_SAME_ACCESS
);
9517 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9518 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9520 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9523 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9524 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9526 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9529 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9530 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9532 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9536 /* unfortunately, atexit depends on implementation of malloc */
9537 /* atexit (term_ntproc); */
9540 /* Make sure we start with all signals unblocked. */
9541 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9542 signal (SIGABRT
, term_ntproc
);
9546 /* determine which drives are fixed, for GetCachedVolumeInformation */
9548 /* GetDriveType must have trailing backslash. */
9549 char drive
[] = "A:\\";
9551 /* Loop over all possible drive letters */
9552 while (*drive
<= 'Z')
9554 /* Record if this drive letter refers to a fixed drive. */
9555 fixed_drives
[DRIVE_INDEX (*drive
)] =
9556 (GetDriveType (drive
) == DRIVE_FIXED
);
9561 /* Reset the volume info cache. */
9562 volume_cache
= NULL
;
9567 shutdown_handler ensures that buffers' autosave files are
9568 up to date when the user logs off, or the system shuts down.
9571 shutdown_handler (DWORD type
)
9573 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9574 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9575 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9576 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9578 /* Shut down cleanly, making sure autosave files are up to date. */
9579 shut_down_emacs (0, Qnil
);
9582 /* Allow other handlers to handle this signal. */
9586 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9587 NT, return a handle to GDI32.DLL. */
9589 maybe_load_unicows_dll (void)
9591 if (os_subtype
== OS_9X
)
9593 HANDLE ret
= LoadLibrary ("Unicows.dll");
9596 /* These two functions are present on Windows 9X as stubs
9597 that always fail. We need the real implementations from
9598 UNICOWS.DLL, so we must call these functions through
9599 pointers, and assign the correct addresses to these
9600 pointers at program startup (see emacs.c, which calls
9601 this function early on). */
9602 pMultiByteToWideChar
=
9603 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9604 pWideCharToMultiByte
=
9605 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9606 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9613 button
= MessageBox (NULL
,
9614 "Emacs cannot load the UNICOWS.DLL library.\n"
9615 "This library is essential for using Emacs\n"
9616 "on this system. You need to install it.\n\n"
9617 "Emacs will exit when you click OK.",
9618 "Emacs cannot load UNICOWS.DLL",
9619 MB_ICONERROR
| MB_TASKMODAL
9620 | MB_SETFOREGROUND
| MB_OK
);
9631 /* On NT family of Windows, these two functions are always
9632 linked in, so we just assign their addresses to the 2
9633 pointers; no need for the LoadLibrary dance. */
9634 pMultiByteToWideChar
= MultiByteToWideChar
;
9635 pWideCharToMultiByte
= WideCharToMultiByte
;
9636 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9637 if (w32_major_version
< 5)
9638 multiByteToWideCharFlags
= 0;
9640 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9641 return LoadLibrary ("Gdi32.dll");
9646 globals_of_w32 is used to initialize those global variables that
9647 must always be initialized on startup even when the global variable
9648 initialized is non zero (see the function main in emacs.c).
9651 globals_of_w32 (void)
9653 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9655 get_process_times_fn
= (GetProcessTimes_Proc
)
9656 GetProcAddress (kernel32
, "GetProcessTimes");
9658 DEFSYM (QCloaded_from
, ":loaded-from");
9660 g_b_init_is_windows_9x
= 0;
9661 g_b_init_open_process_token
= 0;
9662 g_b_init_get_token_information
= 0;
9663 g_b_init_lookup_account_sid
= 0;
9664 g_b_init_get_sid_sub_authority
= 0;
9665 g_b_init_get_sid_sub_authority_count
= 0;
9666 g_b_init_get_security_info
= 0;
9667 g_b_init_get_file_security_w
= 0;
9668 g_b_init_get_file_security_a
= 0;
9669 g_b_init_get_security_descriptor_owner
= 0;
9670 g_b_init_get_security_descriptor_group
= 0;
9671 g_b_init_is_valid_sid
= 0;
9672 g_b_init_create_toolhelp32_snapshot
= 0;
9673 g_b_init_process32_first
= 0;
9674 g_b_init_process32_next
= 0;
9675 g_b_init_open_thread_token
= 0;
9676 g_b_init_impersonate_self
= 0;
9677 g_b_init_revert_to_self
= 0;
9678 g_b_init_get_process_memory_info
= 0;
9679 g_b_init_get_process_working_set_size
= 0;
9680 g_b_init_global_memory_status
= 0;
9681 g_b_init_global_memory_status_ex
= 0;
9682 g_b_init_equal_sid
= 0;
9683 g_b_init_copy_sid
= 0;
9684 g_b_init_get_length_sid
= 0;
9685 g_b_init_get_native_system_info
= 0;
9686 g_b_init_get_system_times
= 0;
9687 g_b_init_create_symbolic_link_w
= 0;
9688 g_b_init_create_symbolic_link_a
= 0;
9689 g_b_init_get_security_descriptor_dacl
= 0;
9690 g_b_init_convert_sd_to_sddl
= 0;
9691 g_b_init_convert_sddl_to_sd
= 0;
9692 g_b_init_is_valid_security_descriptor
= 0;
9693 g_b_init_set_file_security_w
= 0;
9694 g_b_init_set_file_security_a
= 0;
9695 g_b_init_set_named_security_info_w
= 0;
9696 g_b_init_set_named_security_info_a
= 0;
9697 g_b_init_get_adapters_info
= 0;
9698 g_b_init_compare_string_w
= 0;
9699 g_b_init_debug_break_process
= 0;
9700 num_of_processors
= 0;
9701 /* The following sets a handler for shutdown notifications for
9702 console apps. This actually applies to Emacs in both console and
9703 GUI modes, since we had to fool windows into thinking emacs is a
9704 console application to get console mode to work. */
9705 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9707 /* "None" is the default group name on standalone workstations. */
9708 strcpy (dflt_group_name
, "None");
9710 /* Reset, in case it has some value inherited from dump time. */
9711 w32_stat_get_owner_group
= 0;
9713 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9714 (a.k.a. "wide") APIs to invoke functions that accept file
9716 if (is_windows_9x ())
9717 w32_unicode_filenames
= 0;
9719 w32_unicode_filenames
= 1;
9722 dynlib_reset_last_error ();
9725 w32_crypto_hprov
= (HCRYPTPROV
)0;
9728 /* For make-serial-process */
9730 serial_open (Lisp_Object port_obj
)
9732 char *port
= SSDATA (port_obj
);
9737 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9738 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9739 if (hnd
== INVALID_HANDLE_VALUE
)
9740 error ("Could not open %s", port
);
9741 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9743 error ("Could not open %s", port
);
9747 error ("Could not create child process");
9749 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9750 fd_info
[ fd
].hnd
= hnd
;
9751 fd_info
[ fd
].flags
|=
9752 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9753 if (fd_info
[ fd
].cp
!= NULL
)
9755 error ("fd_info[fd = %d] is already in use", fd
);
9757 fd_info
[ fd
].cp
= cp
;
9758 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9759 if (cp
->ovl_read
.hEvent
== NULL
)
9760 error ("Could not create read event");
9761 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9762 if (cp
->ovl_write
.hEvent
== NULL
)
9763 error ("Could not create write event");
9768 /* For serial-process-configure */
9770 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9772 Lisp_Object childp2
= Qnil
;
9773 Lisp_Object tem
= Qnil
;
9777 char summary
[4] = "???"; /* This usually becomes "8N1". */
9779 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9780 error ("Not a serial process");
9781 hnd
= fd_info
[ p
->outfd
].hnd
;
9783 childp2
= Fcopy_sequence (p
->childp
);
9785 /* Initialize timeouts for blocking read and blocking write. */
9786 if (!GetCommTimeouts (hnd
, &ct
))
9787 error ("GetCommTimeouts() failed");
9788 ct
.ReadIntervalTimeout
= 0;
9789 ct
.ReadTotalTimeoutMultiplier
= 0;
9790 ct
.ReadTotalTimeoutConstant
= 0;
9791 ct
.WriteTotalTimeoutMultiplier
= 0;
9792 ct
.WriteTotalTimeoutConstant
= 0;
9793 if (!SetCommTimeouts (hnd
, &ct
))
9794 error ("SetCommTimeouts() failed");
9795 /* Read port attributes and prepare default configuration. */
9796 memset (&dcb
, 0, sizeof (dcb
));
9797 dcb
.DCBlength
= sizeof (DCB
);
9798 if (!GetCommState (hnd
, &dcb
))
9799 error ("GetCommState() failed");
9802 dcb
.fAbortOnError
= FALSE
;
9803 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9808 /* Configure speed. */
9809 if (!NILP (Fplist_member (contact
, QCspeed
)))
9810 tem
= Fplist_get (contact
, QCspeed
);
9812 tem
= Fplist_get (p
->childp
, QCspeed
);
9814 dcb
.BaudRate
= XINT (tem
);
9815 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9817 /* Configure bytesize. */
9818 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9819 tem
= Fplist_get (contact
, QCbytesize
);
9821 tem
= Fplist_get (p
->childp
, QCbytesize
);
9823 tem
= make_number (8);
9825 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9826 error (":bytesize must be nil (8), 7, or 8");
9827 dcb
.ByteSize
= XINT (tem
);
9828 summary
[0] = XINT (tem
) + '0';
9829 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9831 /* Configure parity. */
9832 if (!NILP (Fplist_member (contact
, QCparity
)))
9833 tem
= Fplist_get (contact
, QCparity
);
9835 tem
= Fplist_get (p
->childp
, QCparity
);
9836 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9837 error (":parity must be nil (no parity), `even', or `odd'");
9838 dcb
.fParity
= FALSE
;
9839 dcb
.Parity
= NOPARITY
;
9840 dcb
.fErrorChar
= FALSE
;
9845 else if (EQ (tem
, Qeven
))
9849 dcb
.Parity
= EVENPARITY
;
9850 dcb
.fErrorChar
= TRUE
;
9852 else if (EQ (tem
, Qodd
))
9856 dcb
.Parity
= ODDPARITY
;
9857 dcb
.fErrorChar
= TRUE
;
9859 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9861 /* Configure stopbits. */
9862 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9863 tem
= Fplist_get (contact
, QCstopbits
);
9865 tem
= Fplist_get (p
->childp
, QCstopbits
);
9867 tem
= make_number (1);
9869 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9870 error (":stopbits must be nil (1 stopbit), 1, or 2");
9871 summary
[2] = XINT (tem
) + '0';
9872 if (XINT (tem
) == 1)
9873 dcb
.StopBits
= ONESTOPBIT
;
9874 else if (XINT (tem
) == 2)
9875 dcb
.StopBits
= TWOSTOPBITS
;
9876 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9878 /* Configure flowcontrol. */
9879 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9880 tem
= Fplist_get (contact
, QCflowcontrol
);
9882 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9883 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9884 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9885 dcb
.fOutxCtsFlow
= FALSE
;
9886 dcb
.fOutxDsrFlow
= FALSE
;
9887 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9888 dcb
.fDsrSensitivity
= FALSE
;
9889 dcb
.fTXContinueOnXoff
= FALSE
;
9892 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9893 dcb
.XonChar
= 17; /* Control-Q */
9894 dcb
.XoffChar
= 19; /* Control-S */
9897 /* Already configured. */
9899 else if (EQ (tem
, Qhw
))
9901 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9902 dcb
.fOutxCtsFlow
= TRUE
;
9904 else if (EQ (tem
, Qsw
))
9909 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9911 /* Activate configuration. */
9912 if (!SetCommState (hnd
, &dcb
))
9913 error ("SetCommState() failed");
9915 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9916 pset_childp (p
, childp2
);
9919 /* For make-pipe-process */
9921 register_aux_fd (int infd
)
9927 error ("Could not create child process");
9929 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9931 if (fd_info
[ infd
].cp
!= NULL
)
9933 error ("fd_info[fd = %d] is already in use", infd
);
9935 fd_info
[ infd
].cp
= cp
;
9936 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
9942 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9945 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9946 int fd
= process
->infd
;
9948 n
= sys_read (fd
, (char*)buf
, sz
);
9955 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9956 if (err
== EWOULDBLOCK
)
9959 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9965 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9967 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9968 int fd
= process
->outfd
;
9969 ssize_t n
= sys_write (fd
, buf
, sz
);
9971 /* 0 or more bytes written means everything went fine. */
9975 /* Negative bytes written means we got an error in errno.
9976 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9977 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9978 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9982 #endif /* HAVE_GNUTLS */