1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2014 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
10 (at 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 #include <mingw_time.h>
25 #include <stddef.h> /* for offsetof */
28 #include <float.h> /* for DBL_EPSILON */
35 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
37 #include <sys/utime.h>
40 /* must include CRT headers *before* config.h */
43 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
70 #include "epaths.h" /* for SHELL */
75 /* MinGW64 (_W64) defines these in its _mingw.h. */
76 #if defined(__GNUC__) && !defined(_W64)
77 #define _ANONYMOUS_UNION
78 #define _ANONYMOUS_STRUCT
81 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
82 use a different name to avoid compilation problems. */
83 typedef struct _MEMORY_STATUS_EX
{
86 DWORDLONG ullTotalPhys
;
87 DWORDLONG ullAvailPhys
;
88 DWORDLONG ullTotalPageFile
;
89 DWORDLONG ullAvailPageFile
;
90 DWORDLONG ullTotalVirtual
;
91 DWORDLONG ullAvailVirtual
;
92 DWORDLONG ullAvailExtendedVirtual
;
93 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
95 /* These are here so that GDB would know about these data types. This
96 allows to attach GDB to Emacs when a fatal exception is triggered
97 and Windows pops up the "application needs to be closed" dialog.
98 At that point, _gnu_exception_handler, the top-level exception
99 handler installed by the MinGW startup code, is somewhere on the
100 call-stack of the main thread, so going to that call frame and
101 looking at the argument to _gnu_exception_handler, which is a
102 PEXCEPTION_POINTERS pointer, can reveal the exception code
103 (excptr->ExceptionRecord->ExceptionCode) and the address where the
104 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
105 well as some additional information specific to the exception. */
106 PEXCEPTION_POINTERS excptr
;
107 PEXCEPTION_RECORD excprec
;
113 #include <tlhelp32.h>
118 #if _WIN32_WINNT < 0x0500
119 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
120 /* This either is not in psapi.h or guarded by higher value of
121 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
122 defines it in psapi.h */
123 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
125 DWORD PageFaultCount
;
126 SIZE_T PeakWorkingSetSize
;
127 SIZE_T WorkingSetSize
;
128 SIZE_T QuotaPeakPagedPoolUsage
;
129 SIZE_T QuotaPagedPoolUsage
;
130 SIZE_T QuotaPeakNonPagedPoolUsage
;
131 SIZE_T QuotaNonPagedPoolUsage
;
132 SIZE_T PagefileUsage
;
133 SIZE_T PeakPagefileUsage
;
135 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
139 #include <winioctl.h>
146 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
147 define them by hand if not already defined. */
148 #ifndef SDDL_REVISION_1
149 #define SDDL_REVISION_1 1
150 #endif /* SDDL_REVISION_1 */
152 #if defined(_MSC_VER) || defined(_W64)
153 /* MSVC and MinGW64 don't provide the definition of
154 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
155 which cannot be included because it triggers conflicts with other
156 Windows API headers. So we define it here by hand. */
158 typedef struct _REPARSE_DATA_BUFFER
{
160 USHORT ReparseDataLength
;
164 USHORT SubstituteNameOffset
;
165 USHORT SubstituteNameLength
;
166 USHORT PrintNameOffset
;
167 USHORT PrintNameLength
;
170 } SymbolicLinkReparseBuffer
;
172 USHORT SubstituteNameOffset
;
173 USHORT SubstituteNameLength
;
174 USHORT PrintNameOffset
;
175 USHORT PrintNameLength
;
177 } MountPointReparseBuffer
;
180 } GenericReparseBuffer
;
182 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
184 #ifndef FILE_DEVICE_FILE_SYSTEM
185 #define FILE_DEVICE_FILE_SYSTEM 9
187 #ifndef METHOD_BUFFERED
188 #define METHOD_BUFFERED 0
190 #ifndef FILE_ANY_ACCESS
191 #define FILE_ANY_ACCESS 0x00000000
194 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
196 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
197 #ifndef FSCTL_GET_REPARSE_POINT
198 #define FSCTL_GET_REPARSE_POINT \
199 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
203 /* TCP connection support. */
204 #include <sys/socket.h>
223 #include <iphlpapi.h> /* should be after winsock2.h */
227 #include "w32common.h"
229 #include "w32select.h"
231 #include "dispextern.h" /* for xstrcasecmp */
232 #include "coding.h" /* for Vlocale_coding_system */
234 #include "careadlinkat.h"
235 #include "allocator.h"
237 /* For serial_configure and serial_open. */
240 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
241 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
243 Lisp_Object QCloaded_from
;
245 void globals_of_w32 (void);
246 static DWORD
get_rid (PSID
);
247 static int is_symlink (const char *);
248 static char * chase_symlinks (const char *);
249 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
250 static int restore_privilege (TOKEN_PRIVILEGES
*);
251 static BOOL WINAPI
revert_to_self (void);
253 static int sys_access (const char *, int);
254 extern void *e_malloc (size_t);
255 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
256 struct timespec
*, void *);
257 extern int sys_dup (int);
262 /* Initialization states.
264 WARNING: If you add any more such variables for additional APIs,
265 you MUST add initialization for them to globals_of_w32
266 below. This is because these variables might get set
267 to non-NULL values during dumping, but the dumped Emacs
268 cannot reuse those values, because it could be run on a
269 different version of the OS, where API addresses are
271 static BOOL g_b_init_is_windows_9x
;
272 static BOOL g_b_init_open_process_token
;
273 static BOOL g_b_init_get_token_information
;
274 static BOOL g_b_init_lookup_account_sid
;
275 static BOOL g_b_init_get_sid_sub_authority
;
276 static BOOL g_b_init_get_sid_sub_authority_count
;
277 static BOOL g_b_init_get_security_info
;
278 static BOOL g_b_init_get_file_security_w
;
279 static BOOL g_b_init_get_file_security_a
;
280 static BOOL g_b_init_get_security_descriptor_owner
;
281 static BOOL g_b_init_get_security_descriptor_group
;
282 static BOOL g_b_init_is_valid_sid
;
283 static BOOL g_b_init_create_toolhelp32_snapshot
;
284 static BOOL g_b_init_process32_first
;
285 static BOOL g_b_init_process32_next
;
286 static BOOL g_b_init_open_thread_token
;
287 static BOOL g_b_init_impersonate_self
;
288 static BOOL g_b_init_revert_to_self
;
289 static BOOL g_b_init_get_process_memory_info
;
290 static BOOL g_b_init_get_process_working_set_size
;
291 static BOOL g_b_init_global_memory_status
;
292 static BOOL g_b_init_global_memory_status_ex
;
293 static BOOL g_b_init_get_length_sid
;
294 static BOOL g_b_init_equal_sid
;
295 static BOOL g_b_init_copy_sid
;
296 static BOOL g_b_init_get_native_system_info
;
297 static BOOL g_b_init_get_system_times
;
298 static BOOL g_b_init_create_symbolic_link_w
;
299 static BOOL g_b_init_create_symbolic_link_a
;
300 static BOOL g_b_init_get_security_descriptor_dacl
;
301 static BOOL g_b_init_convert_sd_to_sddl
;
302 static BOOL g_b_init_convert_sddl_to_sd
;
303 static BOOL g_b_init_is_valid_security_descriptor
;
304 static BOOL g_b_init_set_file_security_w
;
305 static BOOL g_b_init_set_file_security_a
;
306 static BOOL g_b_init_set_named_security_info_w
;
307 static BOOL g_b_init_set_named_security_info_a
;
308 static BOOL g_b_init_get_adapters_info
;
311 BEGIN: Wrapper functions around OpenProcessToken
312 and other functions in advapi32.dll that are only
313 supported in Windows NT / 2k / XP
315 /* ** Function pointer typedefs ** */
316 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
317 HANDLE ProcessHandle
,
319 PHANDLE TokenHandle
);
320 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
322 TOKEN_INFORMATION_CLASS TokenInformationClass
,
323 LPVOID TokenInformation
,
324 DWORD TokenInformationLength
,
325 PDWORD ReturnLength
);
326 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
327 HANDLE process_handle
,
328 LPFILETIME creation_time
,
329 LPFILETIME exit_time
,
330 LPFILETIME kernel_time
,
331 LPFILETIME user_time
);
333 GetProcessTimes_Proc get_process_times_fn
= NULL
;
336 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
338 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
340 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
341 LPCTSTR lpSystemName
,
346 LPDWORD cbDomainName
,
347 PSID_NAME_USE peUse
);
348 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
351 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
353 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
355 SE_OBJECT_TYPE ObjectType
,
356 SECURITY_INFORMATION SecurityInfo
,
361 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
362 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
364 SECURITY_INFORMATION RequestedInformation
,
365 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
367 LPDWORD lpnLengthNeeded
);
368 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
370 SECURITY_INFORMATION RequestedInformation
,
371 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
373 LPDWORD lpnLengthNeeded
);
374 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
376 SECURITY_INFORMATION SecurityInformation
,
377 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
378 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
380 SECURITY_INFORMATION SecurityInformation
,
381 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
382 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
383 LPCWSTR lpObjectName
,
384 SE_OBJECT_TYPE ObjectType
,
385 SECURITY_INFORMATION SecurityInformation
,
390 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
392 SE_OBJECT_TYPE ObjectType
,
393 SECURITY_INFORMATION SecurityInformation
,
398 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
399 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
401 LPBOOL lpbOwnerDefaulted
);
402 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
403 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
405 LPBOOL lpbGroupDefaulted
);
406 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
407 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
408 LPBOOL lpbDaclPresent
,
410 LPBOOL lpbDaclDefaulted
);
411 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
413 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
415 DWORD th32ProcessID
);
416 typedef BOOL (WINAPI
* Process32First_Proc
) (
418 LPPROCESSENTRY32 lppe
);
419 typedef BOOL (WINAPI
* Process32Next_Proc
) (
421 LPPROCESSENTRY32 lppe
);
422 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
426 PHANDLE TokenHandle
);
427 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
428 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
429 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
430 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
432 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
434 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
436 PSIZE_T lpMinimumWorkingSetSize
,
437 PSIZE_T lpMaximumWorkingSetSize
);
438 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
439 LPMEMORYSTATUS lpBuffer
);
440 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
441 LPMEMORY_STATUS_EX lpBuffer
);
442 typedef BOOL (WINAPI
* CopySid_Proc
) (
443 DWORD nDestinationSidLength
,
444 PSID pDestinationSid
,
446 typedef BOOL (WINAPI
* EqualSid_Proc
) (
449 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
451 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
452 LPSYSTEM_INFO lpSystemInfo
);
453 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
454 LPFILETIME lpIdleTime
,
455 LPFILETIME lpKernelTime
,
456 LPFILETIME lpUserTime
);
457 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
458 LPCWSTR lpSymlinkFileName
,
459 LPCWSTR lpTargetFileName
,
461 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
462 LPCSTR lpSymlinkFileName
,
463 LPCSTR lpTargetFileName
,
465 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
466 LPCTSTR StringSecurityDescriptor
,
467 DWORD StringSDRevision
,
468 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
469 PULONG SecurityDescriptorSize
);
470 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
471 PSECURITY_DESCRIPTOR SecurityDescriptor
,
472 DWORD RequestedStringSDRevision
,
473 SECURITY_INFORMATION SecurityInformation
,
474 LPTSTR
*StringSecurityDescriptor
,
475 PULONG StringSecurityDescriptorLen
);
476 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
477 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
478 PIP_ADAPTER_INFO pAdapterInfo
,
481 /* ** A utility function ** */
485 static BOOL s_b_ret
= 0;
486 OSVERSIONINFO os_ver
;
487 if (g_b_init_is_windows_9x
== 0)
489 g_b_init_is_windows_9x
= 1;
490 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
491 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
492 if (GetVersionEx (&os_ver
))
494 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
500 static Lisp_Object
ltime (ULONGLONG
);
502 /* Get total user and system times for get-internal-run-time.
503 Returns a list of integers if the times are provided by the OS
504 (NT derivatives), otherwise it returns the result of current-time. */
506 w32_get_internal_run_time (void)
508 if (get_process_times_fn
)
510 FILETIME create
, exit
, kernel
, user
;
511 HANDLE proc
= GetCurrentProcess ();
512 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
514 LARGE_INTEGER user_int
, kernel_int
, total
;
515 user_int
.LowPart
= user
.dwLowDateTime
;
516 user_int
.HighPart
= user
.dwHighDateTime
;
517 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
518 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
519 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
520 return ltime (total
.QuadPart
);
524 return Fcurrent_time ();
527 /* ** The wrapper functions ** */
530 open_process_token (HANDLE ProcessHandle
,
534 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
535 HMODULE hm_advapi32
= NULL
;
536 if (is_windows_9x () == TRUE
)
540 if (g_b_init_open_process_token
== 0)
542 g_b_init_open_process_token
= 1;
543 hm_advapi32
= LoadLibrary ("Advapi32.dll");
544 s_pfn_Open_Process_Token
=
545 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
547 if (s_pfn_Open_Process_Token
== NULL
)
552 s_pfn_Open_Process_Token (
560 get_token_information (HANDLE TokenHandle
,
561 TOKEN_INFORMATION_CLASS TokenInformationClass
,
562 LPVOID TokenInformation
,
563 DWORD TokenInformationLength
,
566 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
567 HMODULE hm_advapi32
= NULL
;
568 if (is_windows_9x () == TRUE
)
572 if (g_b_init_get_token_information
== 0)
574 g_b_init_get_token_information
= 1;
575 hm_advapi32
= LoadLibrary ("Advapi32.dll");
576 s_pfn_Get_Token_Information
=
577 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
579 if (s_pfn_Get_Token_Information
== NULL
)
584 s_pfn_Get_Token_Information (
586 TokenInformationClass
,
588 TokenInformationLength
,
594 lookup_account_sid (LPCTSTR lpSystemName
,
599 LPDWORD cbDomainName
,
602 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
603 HMODULE hm_advapi32
= NULL
;
604 if (is_windows_9x () == TRUE
)
608 if (g_b_init_lookup_account_sid
== 0)
610 g_b_init_lookup_account_sid
= 1;
611 hm_advapi32
= LoadLibrary ("Advapi32.dll");
612 s_pfn_Lookup_Account_Sid
=
613 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
615 if (s_pfn_Lookup_Account_Sid
== NULL
)
620 s_pfn_Lookup_Account_Sid (
632 get_sid_sub_authority (PSID pSid
, DWORD n
)
634 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
635 static DWORD zero
= 0U;
636 HMODULE hm_advapi32
= NULL
;
637 if (is_windows_9x () == TRUE
)
641 if (g_b_init_get_sid_sub_authority
== 0)
643 g_b_init_get_sid_sub_authority
= 1;
644 hm_advapi32
= LoadLibrary ("Advapi32.dll");
645 s_pfn_Get_Sid_Sub_Authority
=
646 (GetSidSubAuthority_Proc
) GetProcAddress (
647 hm_advapi32
, "GetSidSubAuthority");
649 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
653 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
657 get_sid_sub_authority_count (PSID pSid
)
659 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
660 static UCHAR zero
= 0U;
661 HMODULE hm_advapi32
= NULL
;
662 if (is_windows_9x () == TRUE
)
666 if (g_b_init_get_sid_sub_authority_count
== 0)
668 g_b_init_get_sid_sub_authority_count
= 1;
669 hm_advapi32
= LoadLibrary ("Advapi32.dll");
670 s_pfn_Get_Sid_Sub_Authority_Count
=
671 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
672 hm_advapi32
, "GetSidSubAuthorityCount");
674 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
678 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
682 get_security_info (HANDLE handle
,
683 SE_OBJECT_TYPE ObjectType
,
684 SECURITY_INFORMATION SecurityInfo
,
689 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
691 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
692 HMODULE hm_advapi32
= NULL
;
693 if (is_windows_9x () == TRUE
)
697 if (g_b_init_get_security_info
== 0)
699 g_b_init_get_security_info
= 1;
700 hm_advapi32
= LoadLibrary ("Advapi32.dll");
701 s_pfn_Get_Security_Info
=
702 (GetSecurityInfo_Proc
) GetProcAddress (
703 hm_advapi32
, "GetSecurityInfo");
705 if (s_pfn_Get_Security_Info
== NULL
)
709 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
710 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
711 ppSecurityDescriptor
));
715 get_file_security (const char *lpFileName
,
716 SECURITY_INFORMATION RequestedInformation
,
717 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
719 LPDWORD lpnLengthNeeded
)
721 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
722 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
723 HMODULE hm_advapi32
= NULL
;
724 if (is_windows_9x () == TRUE
)
729 if (w32_unicode_filenames
)
731 wchar_t filename_w
[MAX_PATH
];
733 if (g_b_init_get_file_security_w
== 0)
735 g_b_init_get_file_security_w
= 1;
736 hm_advapi32
= LoadLibrary ("Advapi32.dll");
737 s_pfn_Get_File_SecurityW
=
738 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
741 if (s_pfn_Get_File_SecurityW
== NULL
)
746 filename_to_utf16 (lpFileName
, filename_w
);
747 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
748 pSecurityDescriptor
, nLength
,
753 char filename_a
[MAX_PATH
];
755 if (g_b_init_get_file_security_a
== 0)
757 g_b_init_get_file_security_a
= 1;
758 hm_advapi32
= LoadLibrary ("Advapi32.dll");
759 s_pfn_Get_File_SecurityA
=
760 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
763 if (s_pfn_Get_File_SecurityA
== NULL
)
768 filename_to_ansi (lpFileName
, filename_a
);
769 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
770 pSecurityDescriptor
, nLength
,
776 set_file_security (const char *lpFileName
,
777 SECURITY_INFORMATION SecurityInformation
,
778 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
780 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
781 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
782 HMODULE hm_advapi32
= NULL
;
783 if (is_windows_9x () == TRUE
)
788 if (w32_unicode_filenames
)
790 wchar_t filename_w
[MAX_PATH
];
792 if (g_b_init_set_file_security_w
== 0)
794 g_b_init_set_file_security_w
= 1;
795 hm_advapi32
= LoadLibrary ("Advapi32.dll");
796 s_pfn_Set_File_SecurityW
=
797 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
800 if (s_pfn_Set_File_SecurityW
== NULL
)
805 filename_to_utf16 (lpFileName
, filename_w
);
806 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
807 pSecurityDescriptor
));
811 char filename_a
[MAX_PATH
];
813 if (g_b_init_set_file_security_a
== 0)
815 g_b_init_set_file_security_a
= 1;
816 hm_advapi32
= LoadLibrary ("Advapi32.dll");
817 s_pfn_Set_File_SecurityA
=
818 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
821 if (s_pfn_Set_File_SecurityA
== NULL
)
826 filename_to_ansi (lpFileName
, filename_a
);
827 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
828 pSecurityDescriptor
));
833 set_named_security_info (LPCTSTR lpObjectName
,
834 SE_OBJECT_TYPE ObjectType
,
835 SECURITY_INFORMATION SecurityInformation
,
841 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
842 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
843 HMODULE hm_advapi32
= NULL
;
844 if (is_windows_9x () == TRUE
)
849 if (w32_unicode_filenames
)
851 wchar_t filename_w
[MAX_PATH
];
853 if (g_b_init_set_named_security_info_w
== 0)
855 g_b_init_set_named_security_info_w
= 1;
856 hm_advapi32
= LoadLibrary ("Advapi32.dll");
857 s_pfn_Set_Named_Security_InfoW
=
858 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
859 "SetNamedSecurityInfoW");
861 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
866 filename_to_utf16 (lpObjectName
, filename_w
);
867 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
868 SecurityInformation
, psidOwner
,
869 psidGroup
, pDacl
, pSacl
));
873 char filename_a
[MAX_PATH
];
875 if (g_b_init_set_named_security_info_a
== 0)
877 g_b_init_set_named_security_info_a
= 1;
878 hm_advapi32
= LoadLibrary ("Advapi32.dll");
879 s_pfn_Set_Named_Security_InfoA
=
880 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
881 "SetNamedSecurityInfoA");
883 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
888 filename_to_ansi (lpObjectName
, filename_a
);
889 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
890 SecurityInformation
, psidOwner
,
891 psidGroup
, pDacl
, pSacl
));
896 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
898 LPBOOL lpbOwnerDefaulted
)
900 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
901 HMODULE hm_advapi32
= NULL
;
902 if (is_windows_9x () == TRUE
)
907 if (g_b_init_get_security_descriptor_owner
== 0)
909 g_b_init_get_security_descriptor_owner
= 1;
910 hm_advapi32
= LoadLibrary ("Advapi32.dll");
911 s_pfn_Get_Security_Descriptor_Owner
=
912 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
913 hm_advapi32
, "GetSecurityDescriptorOwner");
915 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
920 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
925 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
927 LPBOOL lpbGroupDefaulted
)
929 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
930 HMODULE hm_advapi32
= NULL
;
931 if (is_windows_9x () == TRUE
)
936 if (g_b_init_get_security_descriptor_group
== 0)
938 g_b_init_get_security_descriptor_group
= 1;
939 hm_advapi32
= LoadLibrary ("Advapi32.dll");
940 s_pfn_Get_Security_Descriptor_Group
=
941 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
942 hm_advapi32
, "GetSecurityDescriptorGroup");
944 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
949 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
954 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
955 LPBOOL lpbDaclPresent
,
957 LPBOOL lpbDaclDefaulted
)
959 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
960 HMODULE hm_advapi32
= NULL
;
961 if (is_windows_9x () == TRUE
)
966 if (g_b_init_get_security_descriptor_dacl
== 0)
968 g_b_init_get_security_descriptor_dacl
= 1;
969 hm_advapi32
= LoadLibrary ("Advapi32.dll");
970 s_pfn_Get_Security_Descriptor_Dacl
=
971 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
972 hm_advapi32
, "GetSecurityDescriptorDacl");
974 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
979 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
980 lpbDaclPresent
, pDacl
,
985 is_valid_sid (PSID sid
)
987 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
988 HMODULE hm_advapi32
= NULL
;
989 if (is_windows_9x () == TRUE
)
993 if (g_b_init_is_valid_sid
== 0)
995 g_b_init_is_valid_sid
= 1;
996 hm_advapi32
= LoadLibrary ("Advapi32.dll");
998 (IsValidSid_Proc
) GetProcAddress (
999 hm_advapi32
, "IsValidSid");
1001 if (s_pfn_Is_Valid_Sid
== NULL
)
1005 return (s_pfn_Is_Valid_Sid (sid
));
1009 equal_sid (PSID sid1
, PSID sid2
)
1011 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1012 HMODULE hm_advapi32
= NULL
;
1013 if (is_windows_9x () == TRUE
)
1017 if (g_b_init_equal_sid
== 0)
1019 g_b_init_equal_sid
= 1;
1020 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1022 (EqualSid_Proc
) GetProcAddress (
1023 hm_advapi32
, "EqualSid");
1025 if (s_pfn_Equal_Sid
== NULL
)
1029 return (s_pfn_Equal_Sid (sid1
, sid2
));
1033 get_length_sid (PSID sid
)
1035 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1036 HMODULE hm_advapi32
= NULL
;
1037 if (is_windows_9x () == TRUE
)
1041 if (g_b_init_get_length_sid
== 0)
1043 g_b_init_get_length_sid
= 1;
1044 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1045 s_pfn_Get_Length_Sid
=
1046 (GetLengthSid_Proc
) GetProcAddress (
1047 hm_advapi32
, "GetLengthSid");
1049 if (s_pfn_Get_Length_Sid
== NULL
)
1053 return (s_pfn_Get_Length_Sid (sid
));
1057 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1059 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1060 HMODULE hm_advapi32
= NULL
;
1061 if (is_windows_9x () == TRUE
)
1065 if (g_b_init_copy_sid
== 0)
1067 g_b_init_copy_sid
= 1;
1068 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1070 (CopySid_Proc
) GetProcAddress (
1071 hm_advapi32
, "CopySid");
1073 if (s_pfn_Copy_Sid
== NULL
)
1077 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1081 END: Wrapper functions around OpenProcessToken
1082 and other functions in advapi32.dll that are only
1083 supported in Windows NT / 2k / XP
1087 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1089 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1090 if (is_windows_9x () != TRUE
)
1092 if (g_b_init_get_native_system_info
== 0)
1094 g_b_init_get_native_system_info
= 1;
1095 s_pfn_Get_Native_System_Info
=
1096 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1097 "GetNativeSystemInfo");
1099 if (s_pfn_Get_Native_System_Info
!= NULL
)
1100 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1103 lpSystemInfo
->dwNumberOfProcessors
= -1;
1107 get_system_times (LPFILETIME lpIdleTime
,
1108 LPFILETIME lpKernelTime
,
1109 LPFILETIME lpUserTime
)
1111 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1112 if (is_windows_9x () == TRUE
)
1116 if (g_b_init_get_system_times
== 0)
1118 g_b_init_get_system_times
= 1;
1119 s_pfn_Get_System_times
=
1120 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1123 if (s_pfn_Get_System_times
== NULL
)
1125 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1128 static BOOLEAN WINAPI
1129 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1130 LPCSTR lpTargetFileName
,
1133 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1134 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1137 if (is_windows_9x () == TRUE
)
1142 if (w32_unicode_filenames
)
1144 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1146 if (g_b_init_create_symbolic_link_w
== 0)
1148 g_b_init_create_symbolic_link_w
= 1;
1149 s_pfn_Create_Symbolic_LinkW
=
1150 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1151 "CreateSymbolicLinkW");
1153 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1159 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1160 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1161 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1162 /* If we were denied creation of the symlink, try again after
1163 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1166 TOKEN_PRIVILEGES priv_current
;
1168 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1171 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1172 restore_privilege (&priv_current
);
1179 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1181 if (g_b_init_create_symbolic_link_a
== 0)
1183 g_b_init_create_symbolic_link_a
= 1;
1184 s_pfn_Create_Symbolic_LinkA
=
1185 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1186 "CreateSymbolicLinkA");
1188 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1194 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1195 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1196 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1197 /* If we were denied creation of the symlink, try again after
1198 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1201 TOKEN_PRIVILEGES priv_current
;
1203 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1206 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1207 restore_privilege (&priv_current
);
1216 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1218 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1220 if (is_windows_9x () == TRUE
)
1226 if (g_b_init_is_valid_security_descriptor
== 0)
1228 g_b_init_is_valid_security_descriptor
= 1;
1229 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1230 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1231 "IsValidSecurityDescriptor");
1233 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1239 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1243 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1244 DWORD RequestedStringSDRevision
,
1245 SECURITY_INFORMATION SecurityInformation
,
1246 LPTSTR
*StringSecurityDescriptor
,
1247 PULONG StringSecurityDescriptorLen
)
1249 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1252 if (is_windows_9x () == TRUE
)
1258 if (g_b_init_convert_sd_to_sddl
== 0)
1260 g_b_init_convert_sd_to_sddl
= 1;
1262 s_pfn_Convert_SD_To_SDDL
=
1263 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1264 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1266 s_pfn_Convert_SD_To_SDDL
=
1267 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1268 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1271 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1277 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1278 RequestedStringSDRevision
,
1279 SecurityInformation
,
1280 StringSecurityDescriptor
,
1281 StringSecurityDescriptorLen
);
1287 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1288 DWORD StringSDRevision
,
1289 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1290 PULONG SecurityDescriptorSize
)
1292 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1295 if (is_windows_9x () == TRUE
)
1301 if (g_b_init_convert_sddl_to_sd
== 0)
1303 g_b_init_convert_sddl_to_sd
= 1;
1305 s_pfn_Convert_SDDL_To_SD
=
1306 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1307 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1309 s_pfn_Convert_SDDL_To_SD
=
1310 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1311 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1314 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1320 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1323 SecurityDescriptorSize
);
1329 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1331 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1332 HMODULE hm_iphlpapi
= NULL
;
1334 if (is_windows_9x () == TRUE
)
1335 return ERROR_NOT_SUPPORTED
;
1337 if (g_b_init_get_adapters_info
== 0)
1339 g_b_init_get_adapters_info
= 1;
1340 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1342 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1343 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1345 if (s_pfn_Get_Adapters_Info
== NULL
)
1346 return ERROR_NOT_SUPPORTED
;
1347 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1352 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1353 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1355 This is called from alloc.c:valid_pointer_p. */
1357 w32_valid_pointer_p (void *p
, int size
)
1360 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1364 unsigned char *buf
= alloca (size
);
1365 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1376 /* Here's an overview of how the Windows build supports file names
1377 that cannot be encoded by the current system codepage.
1379 From the POV of Lisp and layers of C code above the functions here,
1380 Emacs on Windows pretends that its file names are encoded in UTF-8;
1381 see encode_file and decode_file on coding.c. Any file name that is
1382 passed as a unibyte string to C functions defined here is assumed
1383 to be in UTF-8 encoding. Any file name returned by functions
1384 defined here must be in UTF-8 encoding, with only a few exceptions
1385 reserved for a couple of special cases. (Be sure to use
1386 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1387 as they can be much longer than MAX_PATH!)
1389 The UTF-8 encoded file names cannot be passed to system APIs, as
1390 Windows does not support that. Therefore, they are converted
1391 either to UTF-16 or to the ANSI codepage, depending on the value of
1392 w32-unicode-filenames, before calling any system APIs or CRT library
1393 functions. The default value of that variable is determined by the
1394 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1395 user can change that default (although I don't see why would she
1398 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1399 filename_from_utf16, and filename_from_ansi, are the workhorses of
1400 these conversions. They rely on Windows native APIs
1401 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1402 functions from coding.c here, because they allocate memory, which
1403 is a bad idea on the level of libc, which is what the functions
1404 here emulate. (If you worry about performance due to constant
1405 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1406 it was measured to take only a few microseconds on a not-so-fast
1407 machine, and second, that's exactly what the ANSI APIs we used
1408 before do anyway, because they are just thin wrappers around the
1411 The variables file-name-coding-system and default-file-name-coding-system
1412 still exist, but are actually used only when a file name needs to
1413 be converted to the ANSI codepage. This happens all the time when
1414 w32-unicode-filenames is nil, but can also happen from time to time
1415 when it is t. Otherwise, these variables have no effect on file-name
1416 encoding when w32-unicode-filenames is t; this is similar to
1417 selection-coding-system.
1419 This arrangement works very well, but it has a few gotchas and
1422 . Lisp code that encodes or decodes file names manually should
1423 normally use 'utf-8' as the coding-system on Windows,
1424 disregarding file-name-coding-system. This is a somewhat
1425 unpleasant consequence, but it cannot be avoided. Fortunately,
1426 very few Lisp packages need to do that.
1428 More generally, passing to library functions (e.g., fopen or
1429 opendir) file names already encoded in the ANSI codepage is
1430 explicitly *verboten*, as all those functions, as shadowed and
1431 emulated here, assume they will receive UTF-8 encoded file names.
1433 For the same reasons, no CRT function or Win32 API can be called
1434 directly in Emacs sources, without either converting the file
1435 name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
1436 through some shadowing function defined here.
1438 . Environment variables stored in Vprocess_environment are encoded
1439 in the ANSI codepage, so if getenv/egetenv is used for a variable
1440 whose value is a file name or a list of directories, it needs to
1441 be converted to UTF-8, before it is used as argument to functions
1442 or decoded into a Lisp string.
1444 . File names passed to external libraries, like the image libraries
1445 and GnuTLS, need special handling. These libraries generally
1446 don't support UTF-16 or UTF-8 file names, so they must get file
1447 names encoded in the ANSI codepage. To facilitate using these
1448 libraries with file names that are not encodable in the ANSI
1449 codepage, use the function ansi_encode_filename, which will try
1450 to use the short 8+3 alias of a file name if that file name is
1451 not encodable in the ANSI codepage. See image.c and gnutls.c for
1452 examples of how this should be done.
1454 . Running subprocesses in non-ASCII directories and with non-ASCII
1455 file arguments is limited to the current codepage (even though
1456 Emacs is perfectly capable of finding an executable program file
1457 even in a directory whose name cannot be encoded in the current
1458 codepage). This is because the command-line arguments are
1459 encoded _before_ they get to the w32-specific level, and the
1460 encoding is not known in advance (it doesn't have to be the
1461 current ANSI codepage), so w32proc.c functions cannot re-encode
1462 them in UTF-16. This should be fixed, but will also require
1463 changes in cmdproxy. The current limitation is not terribly bad
1464 anyway, since very few, if any, Windows console programs that are
1465 likely to be invoked by Emacs support UTF-16 encoded command
1468 . For similar reasons, server.el and emacsclient are also limited
1469 to the current ANSI codepage for now.
1471 . Emacs itself can only handle command-line arguments encoded in
1472 the current codepage.
1474 . Turning on w32-unicode-filename on Windows 9X (if it at all
1475 works) requires UNICOWS.DLL, which is currently loaded only in a
1480 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1481 codepage defined by file-name-coding-system. */
1483 /* Current codepage for encoding file names. */
1484 static int file_name_codepage
;
1486 /* Produce a Windows ANSI codepage suitable for encoding file names.
1487 Return the information about that codepage in CP_INFO. */
1489 codepage_for_filenames (CPINFO
*cp_info
)
1491 /* A simple cache to avoid calling GetCPInfo every time we need to
1492 encode/decode a file name. The file-name encoding is not
1493 supposed to be changed too frequently, if ever. */
1494 static Lisp_Object last_file_name_encoding
;
1496 Lisp_Object current_encoding
;
1498 current_encoding
= Vfile_name_coding_system
;
1499 if (NILP (current_encoding
))
1500 current_encoding
= Vdefault_file_name_coding_system
;
1502 if (!EQ (last_file_name_encoding
, current_encoding
))
1504 /* Default to the current ANSI codepage. */
1505 file_name_codepage
= w32_ansi_code_page
;
1507 if (NILP (current_encoding
))
1509 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1510 char *cp
= NULL
, *end
;
1513 if (strncmp (cpname
, "cp", 2) == 0)
1515 else if (strncmp (cpname
, "windows-", 8) == 0)
1521 cpnum
= strtol (cp
, &end
, 10);
1522 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1523 file_name_codepage
= cpnum
;
1527 if (!file_name_codepage
)
1528 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1530 if (!GetCPInfo (file_name_codepage
, &cp
))
1532 file_name_codepage
= CP_ACP
;
1533 if (!GetCPInfo (file_name_codepage
, &cp
))
1540 return file_name_codepage
;
1544 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1546 int result
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1551 DWORD err
= GetLastError ();
1555 case ERROR_INVALID_FLAGS
:
1556 case ERROR_INVALID_PARAMETER
:
1559 case ERROR_INSUFFICIENT_BUFFER
:
1560 case ERROR_NO_UNICODE_TRANSLATION
:
1571 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1573 int result
= WideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1574 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1578 DWORD err
= GetLastError ();
1582 case ERROR_INVALID_FLAGS
:
1583 case ERROR_INVALID_PARAMETER
:
1586 case ERROR_INSUFFICIENT_BUFFER
:
1587 case ERROR_NO_UNICODE_TRANSLATION
:
1598 filename_to_ansi (const char *fn_in
, char *fn_out
)
1600 wchar_t fn_utf16
[MAX_PATH
];
1602 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1605 int codepage
= codepage_for_filenames (NULL
);
1607 result
= WideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1608 fn_out
, MAX_PATH
, NULL
, NULL
);
1611 DWORD err
= GetLastError ();
1615 case ERROR_INVALID_FLAGS
:
1616 case ERROR_INVALID_PARAMETER
:
1619 case ERROR_INSUFFICIENT_BUFFER
:
1620 case ERROR_NO_UNICODE_TRANSLATION
:
1633 filename_from_ansi (const char *fn_in
, char *fn_out
)
1635 wchar_t fn_utf16
[MAX_PATH
];
1636 int codepage
= codepage_for_filenames (NULL
);
1637 int result
= MultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1638 fn_utf16
, MAX_PATH
);
1642 DWORD err
= GetLastError ();
1646 case ERROR_INVALID_FLAGS
:
1647 case ERROR_INVALID_PARAMETER
:
1650 case ERROR_INSUFFICIENT_BUFFER
:
1651 case ERROR_NO_UNICODE_TRANSLATION
:
1658 return filename_from_utf16 (fn_utf16
, fn_out
);
1663 /* The directory where we started, in UTF-8. */
1664 static char startup_dir
[MAX_UTF8_PATH
];
1666 /* Get the current working directory. */
1668 getcwd (char *dir
, int dirsize
)
1675 if (dirsize
<= strlen (startup_dir
))
1681 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1685 /* Emacs doesn't actually change directory itself, it stays in the
1686 same directory where it was started. */
1687 strcpy (dir
, startup_dir
);
1692 /* Emulate getloadavg. */
1694 struct load_sample
{
1701 /* Number of processors on this machine. */
1702 static unsigned num_of_processors
;
1704 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1705 static struct load_sample samples
[16*60];
1706 static int first_idx
= -1, last_idx
= -1;
1707 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1712 int next_idx
= from
+ 1;
1714 if (next_idx
>= max_idx
)
1723 int prev_idx
= from
- 1;
1726 prev_idx
= max_idx
- 1;
1732 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1734 SYSTEM_INFO sysinfo
;
1735 FILETIME ft_idle
, ft_user
, ft_kernel
;
1737 /* Initialize the number of processors on this machine. */
1738 if (num_of_processors
<= 0)
1740 get_native_system_info (&sysinfo
);
1741 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1742 if (num_of_processors
<= 0)
1744 GetSystemInfo (&sysinfo
);
1745 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1747 if (num_of_processors
<= 0)
1748 num_of_processors
= 1;
1751 /* TODO: Take into account threads that are ready to run, by
1752 sampling the "\System\Processor Queue Length" performance
1753 counter. The code below accounts only for threads that are
1754 actually running. */
1756 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1758 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1760 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1761 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1762 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1763 *idle
= uidle
.QuadPart
;
1764 *kernel
= ukernel
.QuadPart
;
1765 *user
= uuser
.QuadPart
;
1775 /* Produce the load average for a given time interval, using the
1776 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1777 1-minute, 5-minute, or 15-minute average, respectively. */
1781 double retval
= -1.0;
1784 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1785 time_t now
= samples
[last_idx
].sample_time
;
1787 if (first_idx
!= last_idx
)
1789 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1791 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1792 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1795 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1796 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1797 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1799 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1802 if (idx
== first_idx
)
1811 getloadavg (double loadavg
[], int nelem
)
1814 ULONGLONG idle
, kernel
, user
;
1815 time_t now
= time (NULL
);
1817 /* If system time jumped back for some reason, delete all samples
1818 whose time is later than the current wall-clock time. This
1819 prevents load average figures from becoming frozen for prolonged
1820 periods of time, when system time is reset backwards. */
1823 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1825 if (last_idx
== first_idx
)
1827 first_idx
= last_idx
= -1;
1830 last_idx
= buf_prev (last_idx
);
1834 /* Store another sample. We ignore samples that are less than 1 sec
1837 || (difftime (now
, samples
[last_idx
].sample_time
)
1838 >= 1.0 - 2*DBL_EPSILON
*now
))
1840 sample_system_load (&idle
, &kernel
, &user
);
1841 last_idx
= buf_next (last_idx
);
1842 samples
[last_idx
].sample_time
= now
;
1843 samples
[last_idx
].idle
= idle
;
1844 samples
[last_idx
].kernel
= kernel
;
1845 samples
[last_idx
].user
= user
;
1846 /* If the buffer has more that 15 min worth of samples, discard
1848 if (first_idx
== -1)
1849 first_idx
= last_idx
;
1850 while (first_idx
!= last_idx
1851 && (difftime (now
, samples
[first_idx
].sample_time
)
1852 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1853 first_idx
= buf_next (first_idx
);
1856 for (elem
= 0; elem
< nelem
; elem
++)
1858 double avg
= getavg (elem
);
1862 loadavg
[elem
] = avg
;
1868 /* Emulate getpwuid, getpwnam and others. */
1870 #define PASSWD_FIELD_SIZE 256
1872 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1873 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1874 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1875 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1876 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1878 static struct passwd dflt_passwd
=
1890 static char dflt_group_name
[GNLEN
+1];
1892 static struct group dflt_group
=
1894 /* When group information is not available, we return this as the
1895 group for all files. */
1903 return dflt_passwd
.pw_uid
;
1909 /* I could imagine arguing for checking to see whether the user is
1910 in the Administrators group and returning a UID of 0 for that
1911 case, but I don't know how wise that would be in the long run. */
1918 return dflt_passwd
.pw_gid
;
1928 getpwuid (unsigned uid
)
1930 if (uid
== dflt_passwd
.pw_uid
)
1931 return &dflt_passwd
;
1936 getgrgid (gid_t gid
)
1942 getpwnam (char *name
)
1946 pw
= getpwuid (getuid ());
1950 if (xstrcasecmp (name
, pw
->pw_name
))
1957 init_user_info (void)
1959 /* Find the user's real name by opening the process token and
1960 looking up the name associated with the user-sid in that token.
1962 Use the relative portion of the identifier authority value from
1963 the user-sid as the user id value (same for group id using the
1964 primary group sid from the process token). */
1966 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1967 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1968 DWORD glength
= sizeof (gname
);
1969 HANDLE token
= NULL
;
1970 SID_NAME_USE user_type
;
1971 unsigned char *buf
= NULL
;
1973 TOKEN_USER user_token
;
1974 TOKEN_PRIMARY_GROUP group_token
;
1977 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1980 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1981 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1983 buf
= xmalloc (blen
);
1984 result
= get_token_information (token
, TokenUser
,
1985 (LPVOID
)buf
, blen
, &needed
);
1988 memcpy (&user_token
, buf
, sizeof (user_token
));
1989 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1991 domain
, &dlength
, &user_type
);
1999 strcpy (dflt_passwd
.pw_name
, uname
);
2000 /* Determine a reasonable uid value. */
2001 if (xstrcasecmp ("administrator", uname
) == 0)
2003 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2004 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2008 /* Use the last sub-authority value of the RID, the relative
2009 portion of the SID, as user/group ID. */
2010 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2012 /* Get group id and name. */
2013 result
= get_token_information (token
, TokenPrimaryGroup
,
2014 (LPVOID
)buf
, blen
, &needed
);
2015 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2017 buf
= xrealloc (buf
, blen
= needed
);
2018 result
= get_token_information (token
, TokenPrimaryGroup
,
2019 (LPVOID
)buf
, blen
, &needed
);
2023 memcpy (&group_token
, buf
, sizeof (group_token
));
2024 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2025 dlength
= sizeof (domain
);
2026 /* If we can get at the real Primary Group name, use that.
2027 Otherwise, the default group name was already set to
2028 "None" in globals_of_w32. */
2029 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2030 gname
, &glength
, NULL
, &dlength
,
2032 strcpy (dflt_group_name
, gname
);
2035 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2038 /* If security calls are not supported (presumably because we
2039 are running under Windows 9X), fallback to this: */
2040 else if (GetUserName (uname
, &ulength
))
2042 strcpy (dflt_passwd
.pw_name
, uname
);
2043 if (xstrcasecmp ("administrator", uname
) == 0)
2044 dflt_passwd
.pw_uid
= 0;
2046 dflt_passwd
.pw_uid
= 123;
2047 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2051 strcpy (dflt_passwd
.pw_name
, "unknown");
2052 dflt_passwd
.pw_uid
= 123;
2053 dflt_passwd
.pw_gid
= 123;
2055 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2057 /* Set dir and shell from environment variables. */
2058 if (w32_unicode_filenames
)
2060 wchar_t *home
= _wgetenv (L
"HOME");
2061 wchar_t *shell
= _wgetenv (L
"SHELL");
2063 /* Ensure HOME and SHELL are defined. */
2068 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2069 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2073 char *home
= getenv ("HOME");
2074 char *shell
= getenv ("SHELL");
2080 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2081 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2086 CloseHandle (token
);
2092 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2093 return ((rand () << 15) | rand ());
2102 /* Return the maximum length in bytes of a multibyte character
2103 sequence encoded in the current ANSI codepage. This is required to
2104 correctly walk the encoded file names one character at a time. */
2106 max_filename_mbslen (void)
2110 codepage_for_filenames (&cp_info
);
2111 return cp_info
.MaxCharSize
;
2114 /* Normalize filename by converting in-place all of its path
2115 separators to the separator specified by PATH_SEP. */
2118 normalize_filename (register char *fp
, char path_sep
)
2122 /* Always lower-case drive letters a-z, even if the filesystem
2123 preserves case in filenames.
2124 This is so filenames can be compared by string comparison
2125 functions that are case-sensitive. Even case-preserving filesystems
2126 do not distinguish case in drive letters. */
2129 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2137 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2143 /* Destructively turn backslashes into slashes. */
2145 dostounix_filename (register char *p
)
2147 normalize_filename (p
, '/');
2150 /* Destructively turn slashes into backslashes. */
2152 unixtodos_filename (register char *p
)
2154 normalize_filename (p
, '\\');
2157 /* Remove all CR's that are followed by a LF.
2158 (From msdos.c...probably should figure out a way to share it,
2159 although this code isn't going to ever change.) */
2161 crlf_to_lf (register int n
, register unsigned char *buf
)
2163 unsigned char *np
= buf
;
2164 unsigned char *startp
= buf
;
2165 unsigned char *endp
= buf
+ n
;
2169 while (buf
< endp
- 1)
2173 if (*(++buf
) != 0x0a)
2184 /* Parse the root part of file name, if present. Return length and
2185 optionally store pointer to char after root. */
2187 parse_root (const char * name
, const char ** pPath
)
2189 const char * start
= name
;
2194 /* find the root name of the volume if given */
2195 if (isalpha (name
[0]) && name
[1] == ':')
2197 /* skip past drive specifier */
2199 if (IS_DIRECTORY_SEP (name
[0]))
2202 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2209 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2214 if (IS_DIRECTORY_SEP (name
[0]))
2221 return name
- start
;
2224 /* Get long base name for name; name is assumed to be absolute. */
2226 get_long_basename (char * name
, char * buf
, int size
)
2228 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2229 char fname_utf8
[MAX_UTF8_PATH
];
2233 /* Must be valid filename, no wild cards or other invalid characters. */
2234 if (strpbrk (name
, "*?|<>\""))
2237 if (w32_unicode_filenames
)
2239 wchar_t fname_utf16
[MAX_PATH
];
2240 WIN32_FIND_DATAW find_data_wide
;
2242 filename_to_utf16 (name
, fname_utf16
);
2243 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2244 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2245 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2249 char fname_ansi
[MAX_PATH
];
2250 WIN32_FIND_DATAA find_data_ansi
;
2252 filename_to_ansi (name
, fname_ansi
);
2253 /* If the ANSI name includes ? characters, it is not encodable
2254 in the ANSI codepage. In that case, we deliver the question
2255 marks to the caller; calling FindFirstFileA in this case
2256 could return some unrelated file name in the same
2258 if (_mbspbrk (fname_ansi
, "?"))
2260 /* Find the basename of fname_ansi. */
2261 char *p
= strrchr (fname_ansi
, '\\');
2267 cstatus
= filename_from_ansi (p
, fname_utf8
);
2271 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2272 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2273 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2277 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2278 memcpy (buf
, fname_utf8
, len
+ 1);
2282 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2283 FindClose (dir_handle
);
2288 /* Get long name for file, if possible (assumed to be absolute). */
2290 w32_get_long_filename (char * name
, char * buf
, int size
)
2295 char full
[ MAX_UTF8_PATH
];
2298 len
= strlen (name
);
2299 if (len
>= MAX_UTF8_PATH
)
2302 /* Use local copy for destructive modification. */
2303 memcpy (full
, name
, len
+1);
2304 unixtodos_filename (full
);
2306 /* Copy root part verbatim. */
2307 len
= parse_root (full
, (const char **)&p
);
2308 memcpy (o
, full
, len
);
2313 while (p
!= NULL
&& *p
)
2316 p
= strchr (q
, '\\');
2318 len
= get_long_basename (full
, o
, size
);
2341 w32_get_short_filename (char * name
, char * buf
, int size
)
2343 if (w32_unicode_filenames
)
2345 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2346 unsigned int retval
;
2348 filename_to_utf16 (name
, name_utf16
);
2349 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2350 if (retval
&& retval
< size
)
2351 filename_from_utf16 (short_name
, buf
);
2356 char name_ansi
[MAX_PATH
];
2358 filename_to_ansi (name
, name_ansi
);
2359 return GetShortPathNameA (name_ansi
, buf
, size
);
2363 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2364 MS-Windows ANSI codepage. If FILENAME includes characters not
2365 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2366 if it exists. This is needed because the w32 build wants to
2367 support file names outside of the system locale, but image
2368 libraries typically don't support wide (a.k.a. "Unicode") APIs
2369 required for that. */
2372 ansi_encode_filename (Lisp_Object filename
)
2374 Lisp_Object encoded_filename
;
2375 char fname
[MAX_PATH
];
2377 filename_to_ansi (SSDATA (filename
), fname
);
2378 if (_mbspbrk (fname
, "?"))
2380 char shortname
[MAX_PATH
];
2382 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2384 dostounix_filename (shortname
);
2385 encoded_filename
= build_string (shortname
);
2389 encoded_filename
= build_unibyte_string (fname
);
2390 return encoded_filename
;
2394 is_unc_volume (const char *filename
)
2396 const char *ptr
= filename
;
2398 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2401 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2407 /* Emulate the Posix unsetenv. */
2409 unsetenv (const char *name
)
2415 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2420 name_len
= strlen (name
);
2421 /* MS docs says an environment variable cannot be longer than 32K. */
2422 if (name_len
> 32767)
2427 /* It is safe to use 'alloca' with 32K size, since the stack is at
2428 least 2MB, and we set it to 8MB in the link command line. */
2429 var
= alloca (name_len
+ 2);
2430 strncpy (var
, name
, name_len
);
2431 var
[name_len
++] = '=';
2432 var
[name_len
] = '\0';
2433 return _putenv (var
);
2436 /* MS _putenv doesn't support removing a variable when the argument
2437 does not include the '=' character, so we fix that here. */
2439 sys_putenv (char *str
)
2441 const char *const name_end
= strchr (str
, '=');
2443 if (name_end
== NULL
)
2445 /* Remove the variable from the environment. */
2446 return unsetenv (str
);
2449 return _putenv (str
);
2452 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2455 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2458 HKEY hrootkey
= NULL
;
2461 /* Check both the current user and the local machine to see if
2462 we have any resources. */
2464 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2468 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2469 && (lpvalue
= xmalloc (cbData
)) != NULL
2470 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2472 RegCloseKey (hrootkey
);
2478 RegCloseKey (hrootkey
);
2481 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2485 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2486 && (lpvalue
= xmalloc (cbData
)) != NULL
2487 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2489 RegCloseKey (hrootkey
);
2495 RegCloseKey (hrootkey
);
2501 /* The argv[] array holds ANSI-encoded strings, and so this function
2502 works with ANS_encoded strings. */
2504 init_environment (char ** argv
)
2506 static const char * const tempdirs
[] = {
2507 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2512 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2514 /* Implementation note: This function explicitly works with ANSI
2515 file names, not with UTF-8 encoded file names. This is because
2516 this function pushes variables into the Emacs's environment, and
2517 the environment variables are always assumed to be in the
2518 locale-specific encoding. Do NOT call any functions that accept
2519 UTF-8 file names from this function! */
2521 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2522 temporary files and assume "/tmp" if $TMPDIR is unset, which
2523 will break on DOS/Windows. Refuse to work if we cannot find
2524 a directory, not even "c:/", usable for that purpose. */
2525 for (i
= 0; i
< imax
; i
++)
2527 const char *tmp
= tempdirs
[i
];
2530 tmp
= getenv (tmp
+ 1);
2531 /* Note that `access' can lie to us if the directory resides on a
2532 read-only filesystem, like CD-ROM or a write-protected floppy.
2533 The only way to be really sure is to actually create a file and
2534 see if it succeeds. But I think that's too much to ask. */
2536 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2537 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2539 char * var
= alloca (strlen (tmp
) + 8);
2540 sprintf (var
, "TMPDIR=%s", tmp
);
2541 _putenv (strdup (var
));
2548 Fcons (build_string ("no usable temporary directories found!!"),
2550 "While setting TMPDIR: ");
2552 /* Check for environment variables and use registry settings if they
2553 don't exist. Fallback on default values where applicable. */
2558 char locale_name
[32];
2559 char default_home
[MAX_PATH
];
2562 static const struct env_entry
2568 /* If the default value is NULL, we will use the value from the
2569 outside environment or the Registry, but will not push the
2570 variable into the Emacs environment if it is defined neither
2571 in the Registry nor in the outside environment. */
2573 {"PRELOAD_WINSOCK", NULL
},
2574 {"emacs_dir", "C:/emacs"},
2575 {"EMACSLOADPATH", NULL
},
2576 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2577 {"EMACSDATA", NULL
},
2578 {"EMACSPATH", NULL
},
2585 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2587 /* We need to copy dflt_envvars[] and work on the copy because we
2588 don't want the dumped Emacs to inherit the values of
2589 environment variables we saw during dumping (which could be on
2590 a different system). The defaults above must be left intact. */
2591 struct env_entry env_vars
[N_ENV_VARS
];
2593 for (i
= 0; i
< N_ENV_VARS
; i
++)
2594 env_vars
[i
] = dflt_envvars
[i
];
2596 /* For backwards compatibility, check if a .emacs file exists in C:/
2597 If not, then we can try to default to the appdata directory under the
2598 user's profile, which is more likely to be writable. */
2599 if (sys_access ("C:/.emacs", F_OK
) != 0)
2601 HRESULT profile_result
;
2602 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2603 of Windows 95 and NT4 that have not been updated to include
2605 ShGetFolderPath_fn get_folder_path
;
2606 get_folder_path
= (ShGetFolderPath_fn
)
2607 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2609 if (get_folder_path
!= NULL
)
2611 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2614 /* If we can't get the appdata dir, revert to old behavior. */
2615 if (profile_result
== S_OK
)
2617 env_vars
[0].def_value
= default_home
;
2623 /* Get default locale info and use it for LANG. */
2624 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2625 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2626 locale_name
, sizeof (locale_name
)))
2628 for (i
= 0; i
< N_ENV_VARS
; i
++)
2630 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2632 env_vars
[i
].def_value
= locale_name
;
2638 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2640 /* Treat emacs_dir specially: set it unconditionally based on our
2644 char modname
[MAX_PATH
];
2646 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2648 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2652 if ((p
= _mbsrchr (modname
, '\\'))
2653 /* From bin means installed Emacs, from src means uninstalled. */
2654 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2656 char buf
[SET_ENV_BUF_SIZE
];
2657 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2660 for (p
= modname
; *p
; p
= CharNext (p
))
2661 if (*p
== '\\') *p
= '/';
2663 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2664 _putenv (strdup (buf
));
2665 /* If we are running from the Posix-like build tree, define
2666 SHELL to point to our own cmdproxy. The loop below will
2667 then disregard PATH_EXEC and the default value. */
2668 if (within_build_tree
)
2670 _snprintf (buf
, sizeof (buf
) - 1,
2671 "SHELL=%s/nt/cmdproxy.exe", modname
);
2672 _putenv (strdup (buf
));
2677 for (i
= 0; i
< N_ENV_VARS
; i
++)
2679 if (!getenv (env_vars
[i
].name
))
2682 char bufc
[SET_ENV_BUF_SIZE
];
2684 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2685 /* Also ignore empty environment variables. */
2690 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2692 /* Look for cmdproxy.exe in every directory in
2693 PATH_EXEC. FIXME: This does not find cmdproxy
2694 in nt/ when we run uninstalled. */
2695 char fname
[MAX_PATH
];
2696 const char *pstart
= PATH_EXEC
, *pend
;
2699 pend
= _mbschr (pstart
, ';');
2701 pend
= pstart
+ strlen (pstart
);
2702 /* Be defensive against series of ;;; characters. */
2705 strncpy (fname
, pstart
, pend
- pstart
);
2706 fname
[pend
- pstart
] = '/';
2707 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2708 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2710 if (sys_access (bufc
, F_OK
) == 0)
2723 /* If not found in any directory, use the
2724 default as the last resort. */
2725 lpval
= env_vars
[i
].def_value
;
2726 dwType
= REG_EXPAND_SZ
;
2732 lpval
= env_vars
[i
].def_value
;
2733 dwType
= REG_EXPAND_SZ
;
2735 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2736 Vdelayed_warnings_list
2737 = Fcons (listn (CONSTYPE_HEAP
, 2,
2738 intern ("initialization"),
2739 build_string ("Setting HOME to C:\\ by default is deprecated")),
2740 Vdelayed_warnings_list
);
2745 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2747 if (dwType
== REG_EXPAND_SZ
)
2748 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2749 else if (dwType
== REG_SZ
)
2750 strcpy (buf1
, lpval
);
2751 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2753 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2755 _putenv (strdup (buf2
));
2765 /* Rebuild system configuration to reflect invoking system. */
2766 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2768 /* Another special case: on NT, the PATH variable is actually named
2769 "Path" although cmd.exe (perhaps NT itself) arranges for
2770 environment variable lookup and setting to be case insensitive.
2771 However, Emacs assumes a fully case sensitive environment, so we
2772 need to change "Path" to "PATH" to match the expectations of
2773 various elisp packages. We do this by the sneaky method of
2774 modifying the string in the C runtime environ entry.
2776 The same applies to COMSPEC. */
2780 for (envp
= environ
; *envp
; envp
++)
2781 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2782 memcpy (*envp
, "PATH=", 5);
2783 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2784 memcpy (*envp
, "COMSPEC=", 8);
2787 /* Remember the initial working directory for getcwd. */
2788 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2789 Does it matter anywhere in Emacs? */
2790 if (w32_unicode_filenames
)
2792 wchar_t wstartup_dir
[MAX_PATH
];
2794 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2796 filename_from_utf16 (wstartup_dir
, startup_dir
);
2800 char astartup_dir
[MAX_PATH
];
2802 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2804 filename_from_ansi (astartup_dir
, startup_dir
);
2808 static char modname
[MAX_PATH
];
2810 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2815 /* Determine if there is a middle mouse button, to allow parse_button
2816 to decide whether right mouse events should be mouse-2 or
2818 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2823 /* Called from expand-file-name when default-directory is not a string. */
2826 emacs_root_dir (void)
2828 static char root_dir
[MAX_UTF8_PATH
];
2831 p
= getenv ("emacs_dir");
2834 filename_from_ansi (p
, root_dir
);
2835 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2836 dostounix_filename (root_dir
);
2840 #include <sys/timeb.h>
2842 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2844 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2849 tv
->tv_sec
= tb
.time
;
2850 tv
->tv_usec
= tb
.millitm
* 1000L;
2851 /* Implementation note: _ftime sometimes doesn't update the dstflag
2852 according to the new timezone when the system timezone is
2853 changed. We could fix that by using GetSystemTime and
2854 GetTimeZoneInformation, but that doesn't seem necessary, since
2855 Emacs always calls gettimeofday with the 2nd argument NULL (see
2856 current_emacs_time). */
2859 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2860 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2865 /* Emulate fdutimens. */
2867 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2868 TIMESPEC[0] and TIMESPEC[1], respectively.
2869 FD must be either negative -- in which case it is ignored --
2870 or a file descriptor that is open on FILE.
2871 If FD is nonnegative, then FILE can be NULL, which means
2872 use just futimes instead of utimes.
2873 If TIMESPEC is null, FAIL.
2874 Return 0 on success, -1 (setting errno) on failure. */
2877 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2884 if (fd
< 0 && !file
)
2889 /* _futime's prototype defines 2nd arg as having the type 'struct
2890 _utimbuf', while utime needs to accept 'struct utimbuf' for
2891 compatibility with Posix. So we need to use 2 different (but
2892 equivalent) types to avoid compiler warnings, sigh. */
2895 struct _utimbuf _ut
;
2897 _ut
.actime
= timespec
[0].tv_sec
;
2898 _ut
.modtime
= timespec
[1].tv_sec
;
2899 return _futime (fd
, &_ut
);
2905 ut
.actime
= timespec
[0].tv_sec
;
2906 ut
.modtime
= timespec
[1].tv_sec
;
2907 /* Call 'utime', which is implemented below, not the MS library
2908 function, which fails on directories. */
2909 return utime (file
, &ut
);
2914 /* ------------------------------------------------------------------------- */
2915 /* IO support and wrapper functions for the Windows API. */
2916 /* ------------------------------------------------------------------------- */
2918 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2919 on network directories, so we handle that case here.
2920 (Ulrich Leodolter, 1/11/95). */
2922 sys_ctime (const time_t *t
)
2924 char *str
= (char *) ctime (t
);
2925 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2928 /* Emulate sleep...we could have done this with a define, but that
2929 would necessitate including windows.h in the files that used it.
2930 This is much easier. */
2932 sys_sleep (int seconds
)
2934 Sleep (seconds
* 1000);
2937 /* Internal MSVC functions for low-level descriptor munging */
2938 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2939 extern int __cdecl
_free_osfhnd (int fd
);
2941 /* parallel array of private info on file handles */
2942 filedesc fd_info
[ MAXDESC
];
2944 typedef struct volume_info_data
{
2945 struct volume_info_data
* next
;
2947 /* time when info was obtained */
2950 /* actual volume info */
2959 /* Global referenced by various functions. */
2960 static volume_info_data volume_info
;
2962 /* Vector to indicate which drives are local and fixed (for which cached
2963 data never expires). */
2964 static BOOL fixed_drives
[26];
2966 /* Consider cached volume information to be stale if older than 10s,
2967 at least for non-local drives. Info for fixed drives is never stale. */
2968 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2969 #define VOLINFO_STILL_VALID( root_dir, info ) \
2970 ( ( isalpha (root_dir[0]) && \
2971 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2972 || GetTickCount () - info->timestamp < 10000 )
2974 /* Cache support functions. */
2976 /* Simple linked list with linear search is sufficient. */
2977 static volume_info_data
*volume_cache
= NULL
;
2979 static volume_info_data
*
2980 lookup_volume_info (char * root_dir
)
2982 volume_info_data
* info
;
2984 for (info
= volume_cache
; info
; info
= info
->next
)
2985 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2991 add_volume_info (char * root_dir
, volume_info_data
* info
)
2993 info
->root_dir
= xstrdup (root_dir
);
2994 unixtodos_filename (info
->root_dir
);
2995 info
->next
= volume_cache
;
2996 volume_cache
= info
;
3000 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3001 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3002 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3003 static volume_info_data
*
3004 GetCachedVolumeInformation (char * root_dir
)
3006 volume_info_data
* info
;
3007 char default_root
[ MAX_UTF8_PATH
];
3008 char name
[MAX_PATH
+1];
3009 char type
[MAX_PATH
+1];
3011 /* NULL for root_dir means use root from current directory. */
3012 if (root_dir
== NULL
)
3014 if (w32_unicode_filenames
)
3016 wchar_t curdirw
[MAX_PATH
];
3018 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3020 filename_from_utf16 (curdirw
, default_root
);
3024 char curdira
[MAX_PATH
];
3026 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3028 filename_from_ansi (curdira
, default_root
);
3030 parse_root (default_root
, (const char **)&root_dir
);
3032 root_dir
= default_root
;
3035 /* Local fixed drives can be cached permanently. Removable drives
3036 cannot be cached permanently, since the volume name and serial
3037 number (if nothing else) can change. Remote drives should be
3038 treated as if they are removable, since there is no sure way to
3039 tell whether they are or not. Also, the UNC association of drive
3040 letters mapped to remote volumes can be changed at any time (even
3041 by other processes) without notice.
3043 As a compromise, so we can benefit from caching info for remote
3044 volumes, we use a simple expiry mechanism to invalidate cache
3045 entries that are more than ten seconds old. */
3048 /* No point doing this, because WNetGetConnection is even slower than
3049 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3050 GetDriveType is about the only call of this type which does not
3051 involve network access, and so is extremely quick). */
3053 /* Map drive letter to UNC if remote. */
3054 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3056 char remote_name
[ 256 ];
3057 char drive
[3] = { root_dir
[0], ':' };
3059 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3061 /* do something */ ;
3065 info
= lookup_volume_info (root_dir
);
3067 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3073 /* Info is not cached, or is stale. */
3074 if (w32_unicode_filenames
)
3076 wchar_t root_w
[MAX_PATH
];
3077 wchar_t name_w
[MAX_PATH
+1];
3078 wchar_t type_w
[MAX_PATH
+1];
3080 filename_to_utf16 (root_dir
, root_w
);
3081 if (!GetVolumeInformationW (root_w
,
3082 name_w
, sizeof (name_w
),
3086 type_w
, sizeof (type_w
)))
3088 /* Hmm... not really 100% correct, as these 2 are not file
3090 filename_from_utf16 (name_w
, name
);
3091 filename_from_utf16 (type_w
, type
);
3095 char root_a
[MAX_PATH
];
3096 char name_a
[MAX_PATH
+1];
3097 char type_a
[MAX_PATH
+1];
3099 filename_to_ansi (root_dir
, root_a
);
3100 if (!GetVolumeInformationA (root_a
,
3101 name_a
, sizeof (name_a
),
3105 type_a
, sizeof (type_a
)))
3107 filename_from_ansi (name_a
, name
);
3108 filename_from_ansi (type_a
, type
);
3111 /* Cache the volume information for future use, overwriting existing
3112 entry if present. */
3115 info
= xmalloc (sizeof (volume_info_data
));
3116 add_volume_info (root_dir
, info
);
3124 info
->name
= xstrdup (name
);
3125 unixtodos_filename (info
->name
);
3126 info
->serialnum
= serialnum
;
3127 info
->maxcomp
= maxcomp
;
3128 info
->flags
= flags
;
3129 info
->type
= xstrdup (type
);
3130 info
->timestamp
= GetTickCount ();
3136 /* Get information on the volume where NAME is held; set path pointer to
3137 start of pathname in NAME (past UNC header\volume header if present),
3138 if pPath is non-NULL.
3140 Note: if NAME includes symlinks, the information is for the volume
3141 of the symlink, not of its target. That's because, even though
3142 GetVolumeInformation returns information about the symlink target
3143 of its argument, we only pass the root directory to
3144 GetVolumeInformation, not the full NAME. */
3146 get_volume_info (const char * name
, const char ** pPath
)
3148 char temp
[MAX_UTF8_PATH
];
3149 char *rootname
= NULL
; /* default to current volume */
3150 volume_info_data
* info
;
3151 int root_len
= parse_root (name
, pPath
);
3156 /* Copy the root name of the volume, if given. */
3159 strncpy (temp
, name
, root_len
);
3160 temp
[root_len
] = '\0';
3161 unixtodos_filename (temp
);
3165 info
= GetCachedVolumeInformation (rootname
);
3168 /* Set global referenced by other functions. */
3169 volume_info
= *info
;
3175 /* Determine if volume is FAT format (ie. only supports short 8.3
3176 names); also set path pointer to start of pathname in name, if
3177 pPath is non-NULL. */
3179 is_fat_volume (const char * name
, const char ** pPath
)
3181 if (get_volume_info (name
, pPath
))
3182 return (volume_info
.maxcomp
== 12);
3186 /* Convert all slashes in a filename to backslashes, and map filename
3187 to a valid 8.3 name if necessary. The result is a pointer to a
3188 static buffer, so CAVEAT EMPTOR! */
3190 map_w32_filename (const char * name
, const char ** pPath
)
3192 static char shortname
[MAX_UTF8_PATH
];
3193 char * str
= shortname
;
3196 const char * save_name
= name
;
3198 if (strlen (name
) >= sizeof (shortname
))
3200 /* Return a filename which will cause callers to fail. */
3201 strcpy (shortname
, "?");
3205 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3207 register int left
= 8; /* maximum number of chars in part */
3208 register int extn
= 0; /* extension added? */
3209 register int dots
= 2; /* maximum number of dots allowed */
3212 *str
++ = *name
++; /* skip past UNC header */
3214 while ((c
= *name
++))
3221 *str
++ = (c
== ':' ? ':' : '\\');
3222 extn
= 0; /* reset extension flags */
3223 dots
= 2; /* max 2 dots */
3224 left
= 8; /* max length 8 for main part */
3229 /* Convert path components of the form .xxx to _xxx,
3230 but leave . and .. as they are. This allows .emacs
3231 to be read as _emacs, for example. */
3235 IS_DIRECTORY_SEP (*name
))
3250 extn
= 1; /* we've got an extension */
3251 left
= 3; /* 3 chars in extension */
3255 /* any embedded dots after the first are converted to _ */
3260 case '#': /* don't lose these, they're important */
3262 str
[-1] = c
; /* replace last character of part */
3265 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3267 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3269 dots
= 0; /* started a path component */
3278 strcpy (shortname
, name
);
3279 unixtodos_filename (shortname
);
3283 *pPath
= shortname
+ (path
- save_name
);
3289 is_exec (const char * name
)
3291 char * p
= strrchr (name
, '.');
3294 && (xstrcasecmp (p
, ".exe") == 0 ||
3295 xstrcasecmp (p
, ".com") == 0 ||
3296 xstrcasecmp (p
, ".bat") == 0 ||
3297 xstrcasecmp (p
, ".cmd") == 0));
3300 /* Emulate the Unix directory procedures opendir, closedir, and
3301 readdir. We rename them to sys_* names because some versions of
3302 MinGW startup code call opendir and readdir to glob wildcards, and
3303 the code that calls them doesn't grok UTF-8 encoded file names we
3304 produce in dirent->d_name[]. */
3306 struct dirent dir_static
; /* simulated directory contents */
3307 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3308 static int dir_is_fat
;
3309 static char dir_pathname
[MAX_UTF8_PATH
];
3310 static WIN32_FIND_DATAW dir_find_data_w
;
3311 static WIN32_FIND_DATAA dir_find_data_a
;
3312 #define DIR_FIND_DATA_W 1
3313 #define DIR_FIND_DATA_A 2
3314 static int last_dir_find_data
= -1;
3316 /* Support shares on a network resource as subdirectories of a read-only
3318 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3319 static HANDLE
open_unc_volume (const char *);
3320 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3321 static void close_unc_volume (HANDLE
);
3324 sys_opendir (const char *filename
)
3328 /* Opening is done by FindFirstFile. However, a read is inherent to
3329 this operation, so we defer the open until read time. */
3331 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3333 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3336 /* Note: We don't support traversal of UNC volumes via symlinks.
3337 Doing so would mean punishing 99.99% of use cases by resolving
3338 all the possible symlinks in FILENAME, recursively. */
3339 if (is_unc_volume (filename
))
3341 wnet_enum_handle
= open_unc_volume (filename
);
3342 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3346 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3353 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3354 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3355 /* Note: We don't support symlinks to file names on FAT volumes.
3356 Doing so would mean punishing 99.99% of use cases by resolving
3357 all the possible symlinks in FILENAME, recursively. */
3358 dir_is_fat
= is_fat_volume (filename
, NULL
);
3364 sys_closedir (DIR *dirp
)
3366 /* If we have a find-handle open, close it. */
3367 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3369 FindClose (dir_find_handle
);
3370 dir_find_handle
= INVALID_HANDLE_VALUE
;
3372 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3374 close_unc_volume (wnet_enum_handle
);
3375 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3377 xfree ((char *) dirp
);
3381 sys_readdir (DIR *dirp
)
3383 int downcase
= !NILP (Vw32_downcase_file_names
);
3385 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3387 if (!read_unc_volume (wnet_enum_handle
,
3388 dir_find_data_w
.cFileName
,
3389 dir_find_data_a
.cFileName
,
3393 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3394 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3396 char filename
[MAX_UTF8_PATH
+ 2];
3399 strcpy (filename
, dir_pathname
);
3400 ln
= strlen (filename
) - 1;
3401 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3402 strcat (filename
, "\\");
3403 strcat (filename
, "*");
3405 /* Note: No need to resolve symlinks in FILENAME, because
3406 FindFirst opens the directory that is the target of a
3408 if (w32_unicode_filenames
)
3410 wchar_t fnw
[MAX_PATH
];
3412 filename_to_utf16 (filename
, fnw
);
3413 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3419 filename_to_ansi (filename
, fna
);
3420 /* If FILENAME is not representable by the current ANSI
3421 codepage, we don't want FindFirstFileA to interpret the
3422 '?' characters as a wildcard. */
3423 if (_mbspbrk (fna
, "?"))
3424 dir_find_handle
= INVALID_HANDLE_VALUE
;
3426 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3429 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3432 else if (w32_unicode_filenames
)
3434 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3439 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3443 /* Emacs never uses this value, so don't bother making it match
3444 value returned by stat(). */
3445 dir_static
.d_ino
= 1;
3447 if (w32_unicode_filenames
)
3449 if (downcase
|| dir_is_fat
)
3451 wchar_t tem
[MAX_PATH
];
3453 wcscpy (tem
, dir_find_data_w
.cFileName
);
3455 filename_from_utf16 (tem
, dir_static
.d_name
);
3458 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3459 last_dir_find_data
= DIR_FIND_DATA_W
;
3465 /* If the file name in cFileName[] includes `?' characters, it
3466 means the original file name used characters that cannot be
3467 represented by the current ANSI codepage. To avoid total
3468 lossage, retrieve the short 8+3 alias of the long file
3470 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3472 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3473 /* 8+3 aliases are returned in all caps, which could break
3474 various alists that look at filenames' extensions. */
3477 else if (downcase
|| dir_is_fat
)
3478 strcpy (tem
, dir_find_data_a
.cFileName
);
3480 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3481 if (downcase
|| dir_is_fat
)
3484 filename_from_ansi (tem
, dir_static
.d_name
);
3486 last_dir_find_data
= DIR_FIND_DATA_A
;
3489 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3490 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3491 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3497 open_unc_volume (const char *path
)
3499 const char *fn
= map_w32_filename (path
, NULL
);
3503 if (w32_unicode_filenames
)
3506 wchar_t fnw
[MAX_PATH
];
3508 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3509 nrw
.dwType
= RESOURCETYPE_DISK
;
3510 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3511 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3512 nrw
.lpLocalName
= NULL
;
3513 filename_to_utf16 (fn
, fnw
);
3514 nrw
.lpRemoteName
= fnw
;
3515 nrw
.lpComment
= NULL
;
3516 nrw
.lpProvider
= NULL
;
3518 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3519 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3526 nra
.dwScope
= RESOURCE_GLOBALNET
;
3527 nra
.dwType
= RESOURCETYPE_DISK
;
3528 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3529 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3530 nra
.lpLocalName
= NULL
;
3531 filename_to_ansi (fn
, fna
);
3532 nra
.lpRemoteName
= fna
;
3533 nra
.lpComment
= NULL
;
3534 nra
.lpProvider
= NULL
;
3536 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3537 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3539 if (result
== NO_ERROR
)
3542 return INVALID_HANDLE_VALUE
;
3546 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3551 DWORD bufsize
= 512;
3555 if (w32_unicode_filenames
)
3560 buffer
= alloca (bufsize
);
3561 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3562 if (result
!= NO_ERROR
)
3564 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3565 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3567 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3569 wcsncpy (fname_w
, ptrw
, size
);
3574 int dbcs_p
= max_filename_mbslen () > 1;
3577 buffer
= alloca (bufsize
);
3578 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3579 if (result
!= NO_ERROR
)
3581 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3584 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3587 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3588 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3591 strncpy (fname_a
, ptra
, size
);
3599 close_unc_volume (HANDLE henum
)
3601 if (henum
!= INVALID_HANDLE_VALUE
)
3602 WNetCloseEnum (henum
);
3606 unc_volume_file_attributes (const char *path
)
3611 henum
= open_unc_volume (path
);
3612 if (henum
== INVALID_HANDLE_VALUE
)
3615 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3617 close_unc_volume (henum
);
3622 /* Ensure a network connection is authenticated. */
3624 logon_network_drive (const char *path
)
3626 char share
[MAX_UTF8_PATH
];
3633 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3634 drvtype
= DRIVE_REMOTE
;
3635 else if (path
[0] == '\0' || path
[1] != ':')
3636 drvtype
= GetDriveType (NULL
);
3643 drvtype
= GetDriveType (drive
);
3646 /* Only logon to networked drives. */
3647 if (drvtype
!= DRIVE_REMOTE
)
3651 strncpy (share
, path
, MAX_UTF8_PATH
);
3652 /* Truncate to just server and share name. */
3653 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3655 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3662 if (w32_unicode_filenames
)
3664 NETRESOURCEW resourcew
;
3665 wchar_t share_w
[MAX_PATH
];
3667 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3668 resourcew
.dwType
= RESOURCETYPE_DISK
;
3669 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3670 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3671 resourcew
.lpLocalName
= NULL
;
3672 filename_to_utf16 (share
, share_w
);
3673 resourcew
.lpRemoteName
= share_w
;
3674 resourcew
.lpProvider
= NULL
;
3676 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3680 NETRESOURCEA resourcea
;
3681 char share_a
[MAX_PATH
];
3683 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3684 resourcea
.dwType
= RESOURCETYPE_DISK
;
3685 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3686 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3687 resourcea
.lpLocalName
= NULL
;
3688 filename_to_ansi (share
, share_a
);
3689 resourcea
.lpRemoteName
= share_a
;
3690 resourcea
.lpProvider
= NULL
;
3692 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3698 case ERROR_ALREADY_ASSIGNED
:
3700 case ERROR_ACCESS_DENIED
:
3701 case ERROR_LOGON_FAILURE
:
3707 case ERROR_BAD_NET_NAME
:
3708 case ERROR_NO_NET_OR_BAD_PATH
:
3709 case ERROR_NO_NETWORK
:
3710 case ERROR_CANCELLED
:
3717 /* Emulate faccessat(2). */
3719 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3723 if (dirfd
!= AT_FDCWD
3724 && !(IS_DIRECTORY_SEP (path
[0])
3725 || IS_DEVICE_SEP (path
[1])))
3731 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3732 newer versions blow up when passed D_OK. */
3733 path
= map_w32_filename (path
, NULL
);
3734 /* If the last element of PATH is a symlink, we need to resolve it
3735 to get the attributes of its target file. Note: any symlinks in
3736 PATH elements other than the last one are transparently resolved
3737 by GetFileAttributes below. */
3738 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3739 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3740 path
= chase_symlinks (path
);
3742 if (w32_unicode_filenames
)
3744 wchar_t path_w
[MAX_PATH
];
3746 filename_to_utf16 (path
, path_w
);
3747 attributes
= GetFileAttributesW (path_w
);
3751 char path_a
[MAX_PATH
];
3753 filename_to_ansi (path
, path_a
);
3754 attributes
= GetFileAttributesA (path_a
);
3757 if (attributes
== -1)
3759 DWORD w32err
= GetLastError ();
3763 case ERROR_INVALID_NAME
:
3764 case ERROR_BAD_PATHNAME
:
3765 if (is_unc_volume (path
))
3767 attributes
= unc_volume_file_attributes (path
);
3768 if (attributes
== -1)
3776 case ERROR_FILE_NOT_FOUND
:
3777 case ERROR_BAD_NETPATH
:
3786 if ((mode
& X_OK
) != 0
3787 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3792 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3797 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3805 /* A version of 'access' to be used locally with file names in
3806 locale-specific encoding. Does not resolve symlinks and does not
3807 support file names on FAT12 and FAT16 volumes, but that's OK, since
3808 we only invoke this function for files inside the Emacs source or
3809 installation tree, on directories (so any symlinks should have the
3810 directory bit set), and on short file names such as "C:/.emacs". */
3812 sys_access (const char *fname
, int mode
)
3814 char fname_copy
[MAX_PATH
], *p
;
3817 strcpy (fname_copy
, fname
);
3818 /* Do the equivalent of unixtodos_filename. */
3819 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3823 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3825 DWORD w32err
= GetLastError ();
3829 case ERROR_INVALID_NAME
:
3830 case ERROR_BAD_PATHNAME
:
3831 case ERROR_FILE_NOT_FOUND
:
3832 case ERROR_BAD_NETPATH
:
3841 if ((mode
& X_OK
) != 0
3842 && !(is_exec (fname_copy
)
3843 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3848 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3853 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3861 /* Shadow some MSVC runtime functions to map requests for long filenames
3862 to reasonable short names if necessary. This was originally added to
3863 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3867 sys_chdir (const char * path
)
3869 path
= map_w32_filename (path
, NULL
);
3870 if (w32_unicode_filenames
)
3872 wchar_t newdir_w
[MAX_PATH
];
3874 if (filename_to_utf16 (path
, newdir_w
) == 0)
3875 return _wchdir (newdir_w
);
3880 char newdir_a
[MAX_PATH
];
3882 if (filename_to_ansi (path
, newdir_a
) == 0)
3883 return _chdir (newdir_a
);
3889 sys_chmod (const char * path
, int mode
)
3891 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3892 if (w32_unicode_filenames
)
3894 wchar_t path_w
[MAX_PATH
];
3896 filename_to_utf16 (path
, path_w
);
3897 return _wchmod (path_w
, mode
);
3901 char path_a
[MAX_PATH
];
3903 filename_to_ansi (path
, path_a
);
3904 return _chmod (path_a
, mode
);
3909 sys_creat (const char * path
, int mode
)
3911 path
= map_w32_filename (path
, NULL
);
3912 if (w32_unicode_filenames
)
3914 wchar_t path_w
[MAX_PATH
];
3916 filename_to_utf16 (path
, path_w
);
3917 return _wcreat (path_w
, mode
);
3921 char path_a
[MAX_PATH
];
3923 filename_to_ansi (path
, path_a
);
3924 return _creat (path_a
, mode
);
3929 sys_fopen (const char * path
, const char * mode
)
3933 const char * mode_save
= mode
;
3935 /* Force all file handles to be non-inheritable. This is necessary to
3936 ensure child processes don't unwittingly inherit handles that might
3937 prevent future file access. */
3941 else if (mode
[0] == 'w' || mode
[0] == 'a')
3942 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3946 /* Only do simplistic option parsing. */
3950 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3953 else if (mode
[0] == 'b')
3958 else if (mode
[0] == 't')
3965 path
= map_w32_filename (path
, NULL
);
3966 if (w32_unicode_filenames
)
3968 wchar_t path_w
[MAX_PATH
];
3970 filename_to_utf16 (path
, path_w
);
3971 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3975 char path_a
[MAX_PATH
];
3977 filename_to_ansi (path
, path_a
);
3978 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3983 return _fdopen (fd
, mode_save
);
3986 /* This only works on NTFS volumes, but is useful to have. */
3988 sys_link (const char * old
, const char * new)
3992 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3993 wchar_t oldname_w
[MAX_PATH
];
3994 char oldname_a
[MAX_PATH
];
3996 if (old
== NULL
|| new == NULL
)
4002 strcpy (oldname
, map_w32_filename (old
, NULL
));
4003 strcpy (newname
, map_w32_filename (new, NULL
));
4005 if (w32_unicode_filenames
)
4007 filename_to_utf16 (oldname
, oldname_w
);
4008 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4009 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4013 filename_to_ansi (oldname
, oldname_a
);
4014 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4015 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4017 if (fileh
!= INVALID_HANDLE_VALUE
)
4021 /* Confusingly, the "alternate" stream name field does not apply
4022 when restoring a hard link, and instead contains the actual
4023 stream data for the link (ie. the name of the link to create).
4024 The WIN32_STREAM_ID structure before the cStreamName field is
4025 the stream header, which is then immediately followed by the
4029 WIN32_STREAM_ID wid
;
4030 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4033 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4034 indicates that flag is unsupported for CP_UTF8, and OTOH says
4035 it is the default anyway. */
4036 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4037 data
.wid
.cStreamName
, MAX_PATH
);
4040 LPVOID context
= NULL
;
4043 data
.wid
.dwStreamId
= BACKUP_LINK
;
4044 data
.wid
.dwStreamAttributes
= 0;
4045 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4046 data
.wid
.Size
.HighPart
= 0;
4047 data
.wid
.dwStreamNameSize
= 0;
4049 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4050 offsetof (WIN32_STREAM_ID
, cStreamName
)
4051 + data
.wid
.Size
.LowPart
,
4052 &wbytes
, FALSE
, FALSE
, &context
)
4053 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4060 DWORD err
= GetLastError ();
4065 case ERROR_ACCESS_DENIED
:
4066 /* This is what happens when OLDNAME is a directory,
4067 since Windows doesn't support hard links to
4068 directories. Posix says to set errno to EPERM in
4070 if (w32_unicode_filenames
)
4071 attributes
= GetFileAttributesW (oldname_w
);
4073 attributes
= GetFileAttributesA (oldname_a
);
4074 if (attributes
!= -1
4075 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4077 else if (attributes
== -1
4078 && is_unc_volume (oldname
)
4079 && unc_volume_file_attributes (oldname
) != -1)
4084 case ERROR_TOO_MANY_LINKS
:
4087 case ERROR_NOT_SAME_DEVICE
:
4097 CloseHandle (fileh
);
4106 sys_mkdir (const char * path
)
4108 path
= map_w32_filename (path
, NULL
);
4110 if (w32_unicode_filenames
)
4112 wchar_t path_w
[MAX_PATH
];
4114 filename_to_utf16 (path
, path_w
);
4115 return _wmkdir (path_w
);
4119 char path_a
[MAX_PATH
];
4121 filename_to_ansi (path
, path_a
);
4122 return _mkdir (path_a
);
4127 sys_open (const char * path
, int oflag
, int mode
)
4129 const char* mpath
= map_w32_filename (path
, NULL
);
4132 if (w32_unicode_filenames
)
4134 wchar_t mpath_w
[MAX_PATH
];
4136 filename_to_utf16 (mpath
, mpath_w
);
4137 /* If possible, try to open file without _O_CREAT, to be able to
4138 write to existing hidden and system files. Force all file
4139 handles to be non-inheritable. */
4140 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4141 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4143 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4147 char mpath_a
[MAX_PATH
];
4149 filename_to_ansi (mpath
, mpath_a
);
4150 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4151 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4153 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4159 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4162 Standard algorithm for generating a temporary file name seems to be
4163 use pid or tid with a letter on the front (in place of the 6 X's)
4164 and cycle through the letters to find a unique name. We extend
4165 that to allow any reasonable character as the first of the 6 X's,
4166 so that the number of simultaneously used temporary files will be
4170 mkostemp (char * template, int flags
)
4174 unsigned uid
= GetCurrentThreadId ();
4175 int save_errno
= errno
;
4176 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4179 if (template == NULL
)
4182 p
= template + strlen (template);
4184 /* replace up to the last 5 X's with uid in decimal */
4185 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4187 p
[0] = '0' + uid
% 10;
4191 if (i
< 0 && p
[0] == 'X')
4196 p
[0] = first_char
[i
];
4197 if ((fd
= sys_open (template,
4198 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4199 S_IRUSR
| S_IWUSR
)) >= 0
4207 while (++i
< sizeof (first_char
));
4210 /* Template is badly formed or else we can't generate a unique name. */
4215 fchmod (int fd
, mode_t mode
)
4221 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4224 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4227 bool have_temp_a
= false;
4229 /* MoveFile on Windows 95 doesn't correctly change the short file name
4230 alias in a number of circumstances (it is not easy to predict when
4231 just by looking at oldname and newname, unfortunately). In these
4232 cases, renaming through a temporary name avoids the problem.
4234 A second problem on Windows 95 is that renaming through a temp name when
4235 newname is uppercase fails (the final long name ends up in
4236 lowercase, although the short alias might be uppercase) UNLESS the
4237 long temp name is not 8.3.
4239 So, on Windows 95 we always rename through a temp name, and we make sure
4240 the temp name has a long extension to ensure correct renaming. */
4242 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4244 /* volume_info is set indirectly by map_w32_filename. */
4245 oldname_dev
= volume_info
.serialnum
;
4247 if (os_subtype
== OS_9X
)
4252 char oldname_a
[MAX_PATH
];
4254 oldname
= map_w32_filename (oldname
, NULL
);
4255 filename_to_ansi (oldname
, oldname_a
);
4256 filename_to_ansi (temp
, temp_a
);
4257 if ((o
= strrchr (oldname_a
, '\\')))
4260 o
= (char *) oldname_a
;
4262 if ((p
= strrchr (temp_a
, '\\')))
4269 /* Force temp name to require a manufactured 8.3 alias - this
4270 seems to make the second rename work properly. */
4271 sprintf (p
, "_.%s.%u", o
, i
);
4273 result
= rename (oldname_a
, temp_a
);
4275 /* This loop must surely terminate! */
4276 while (result
< 0 && errno
== EEXIST
);
4282 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4283 (at least if it is a file; don't do this for directories).
4285 Since we mustn't do this if we are just changing the case of the
4286 file name (we would end up deleting the file we are trying to
4287 rename!), we let rename detect if the destination file already
4288 exists - that way we avoid the possible pitfalls of trying to
4289 determine ourselves whether two names really refer to the same
4290 file, which is not always possible in the general case. (Consider
4291 all the permutations of shared or subst'd drives, etc.) */
4293 newname
= map_w32_filename (newname
, NULL
);
4295 /* volume_info is set indirectly by map_w32_filename. */
4296 newname_dev
= volume_info
.serialnum
;
4298 if (w32_unicode_filenames
)
4300 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4302 filename_to_utf16 (temp
, temp_w
);
4303 filename_to_utf16 (newname
, newname_w
);
4304 result
= _wrename (temp_w
, newname_w
);
4305 if (result
< 0 && force
)
4307 DWORD w32err
= GetLastError ();
4310 && newname_dev
!= oldname_dev
)
4312 /* The implementation of `rename' on Windows does not return
4313 errno = EXDEV when you are moving a directory to a
4314 different storage device (ex. logical disk). It returns
4315 EACCES instead. So here we handle such situations and
4319 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4320 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4323 else if (errno
== EEXIST
)
4325 if (_wchmod (newname_w
, 0666) != 0)
4327 if (_wunlink (newname_w
) != 0)
4329 result
= _wrename (temp_w
, newname_w
);
4331 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4332 && is_symlink (temp
))
4334 /* This is Windows prohibiting the user from creating a
4335 symlink in another place, since that requires
4343 char newname_a
[MAX_PATH
];
4346 filename_to_ansi (temp
, temp_a
);
4347 filename_to_ansi (newname
, newname_a
);
4348 result
= rename (temp_a
, newname_a
);
4349 if (result
< 0 && force
)
4351 DWORD w32err
= GetLastError ();
4354 && newname_dev
!= oldname_dev
)
4358 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4359 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4362 else if (errno
== EEXIST
)
4364 if (_chmod (newname_a
, 0666) != 0)
4366 if (_unlink (newname_a
) != 0)
4368 result
= rename (temp_a
, newname_a
);
4370 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4371 && is_symlink (temp
))
4380 sys_rename (char const *old
, char const *new)
4382 return sys_rename_replace (old
, new, TRUE
);
4386 sys_rmdir (const char * path
)
4388 path
= map_w32_filename (path
, NULL
);
4390 if (w32_unicode_filenames
)
4392 wchar_t path_w
[MAX_PATH
];
4394 filename_to_utf16 (path
, path_w
);
4395 return _wrmdir (path_w
);
4399 char path_a
[MAX_PATH
];
4401 filename_to_ansi (path
, path_a
);
4402 return _rmdir (path_a
);
4407 sys_unlink (const char * path
)
4409 path
= map_w32_filename (path
, NULL
);
4411 if (w32_unicode_filenames
)
4413 wchar_t path_w
[MAX_PATH
];
4415 filename_to_utf16 (path
, path_w
);
4416 /* On Unix, unlink works without write permission. */
4417 _wchmod (path_w
, 0666);
4418 return _wunlink (path_w
);
4422 char path_a
[MAX_PATH
];
4424 filename_to_ansi (path
, path_a
);
4425 _chmod (path_a
, 0666);
4426 return _unlink (path_a
);
4430 static FILETIME utc_base_ft
;
4431 static ULONGLONG utc_base
; /* In 100ns units */
4432 static int init
= 0;
4434 #define FILETIME_TO_U64(result, ft) \
4436 ULARGE_INTEGER uiTemp; \
4437 uiTemp.LowPart = (ft).dwLowDateTime; \
4438 uiTemp.HighPart = (ft).dwHighDateTime; \
4439 result = uiTemp.QuadPart; \
4443 initialize_utc_base (void)
4445 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4454 st
.wMilliseconds
= 0;
4456 SystemTimeToFileTime (&st
, &utc_base_ft
);
4457 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4461 convert_time (FILETIME ft
)
4467 initialize_utc_base ();
4471 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4474 FILETIME_TO_U64 (tmp
, ft
);
4475 return (time_t) ((tmp
- utc_base
) / 10000000L);
4479 convert_from_time_t (time_t time
, FILETIME
* pft
)
4485 initialize_utc_base ();
4489 /* time in 100ns units since 1-Jan-1601 */
4490 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4491 pft
->dwHighDateTime
= tmp
.HighPart
;
4492 pft
->dwLowDateTime
= tmp
.LowPart
;
4495 static PSECURITY_DESCRIPTOR
4496 get_file_security_desc_by_handle (HANDLE h
)
4498 PSECURITY_DESCRIPTOR psd
= NULL
;
4500 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4501 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4503 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4504 NULL
, NULL
, NULL
, NULL
, &psd
);
4505 if (err
!= ERROR_SUCCESS
)
4511 static PSECURITY_DESCRIPTOR
4512 get_file_security_desc_by_name (const char *fname
)
4514 PSECURITY_DESCRIPTOR psd
= NULL
;
4516 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4517 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4519 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4521 err
= GetLastError ();
4522 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4526 psd
= xmalloc (sd_len
);
4527 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4539 unsigned n_subauthorities
;
4541 /* Use the last sub-authority value of the RID, the relative
4542 portion of the SID, as user/group ID. */
4543 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4544 if (n_subauthorities
< 1)
4545 return 0; /* the "World" RID */
4546 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4549 /* Caching SID and account values for faster lokup. */
4553 struct w32_id
*next
;
4555 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4558 static struct w32_id
*w32_idlist
;
4561 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4563 struct w32_id
*tail
, *found
;
4565 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4567 if (equal_sid ((PSID
)tail
->sid
, sid
))
4576 strcpy (name
, found
->name
);
4584 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4587 struct w32_id
*new_entry
;
4589 /* We don't want to leave behind stale cache from when Emacs was
4593 sid_len
= get_length_sid (sid
);
4594 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4597 new_entry
->rid
= id
;
4598 strcpy (new_entry
->name
, name
);
4599 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4600 new_entry
->next
= w32_idlist
;
4601 w32_idlist
= new_entry
;
4610 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4614 SID_NAME_USE ignore
;
4616 DWORD name_len
= sizeof (name
);
4618 DWORD domain_len
= sizeof (domain
);
4623 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4624 else if (what
== GID
)
4625 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4629 if (!result
|| !is_valid_sid (sid
))
4631 else if (!w32_cached_id (sid
, id
, nm
))
4633 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4634 domain
, &domain_len
, &ignore
)
4635 || name_len
> UNLEN
+1)
4639 *id
= get_rid (sid
);
4641 w32_add_to_cache (sid
, *id
, name
);
4648 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4650 int dflt_usr
= 0, dflt_grp
= 0;
4659 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4661 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4664 /* Consider files to belong to current user/group, if we cannot get
4665 more accurate information. */
4668 st
->st_uid
= dflt_passwd
.pw_uid
;
4669 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4673 st
->st_gid
= dflt_passwd
.pw_gid
;
4674 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4678 /* Return non-zero if NAME is a potentially slow filesystem. */
4680 is_slow_fs (const char *name
)
4685 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4686 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4687 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4688 devtype
= GetDriveType (NULL
); /* use root of current drive */
4691 /* GetDriveType needs the root directory of the drive. */
4692 strncpy (drive_root
, name
, 2);
4693 drive_root
[2] = '\\';
4694 drive_root
[3] = '\0';
4695 devtype
= GetDriveType (drive_root
);
4697 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4700 /* If this is non-zero, the caller wants accurate information about
4701 file's owner and group, which could be expensive to get. dired.c
4702 uses this flag when needed for the job at hand. */
4703 int w32_stat_get_owner_group
;
4705 /* MSVC stat function can't cope with UNC names and has other bugs, so
4706 replace it with our own. This also allows us to calculate consistent
4707 inode values and owner/group without hacks in the main Emacs code,
4708 and support file names encoded in UTF-8. */
4711 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4713 char *name
, *save_name
, *r
;
4714 WIN32_FIND_DATAW wfd_w
;
4715 WIN32_FIND_DATAA wfd_a
;
4717 unsigned __int64 fake_inode
= 0;
4720 int rootdir
= FALSE
;
4721 PSECURITY_DESCRIPTOR psd
= NULL
;
4722 int is_a_symlink
= 0;
4723 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4724 DWORD access_rights
= 0;
4725 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4726 FILETIME ctime
, atime
, wtime
;
4727 wchar_t name_w
[MAX_PATH
];
4728 char name_a
[MAX_PATH
];
4730 if (path
== NULL
|| buf
== NULL
)
4736 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4737 /* Must be valid filename, no wild cards or other invalid
4739 if (strpbrk (name
, "*?|<>\""))
4745 /* Remove trailing directory separator, unless name is the root
4746 directory of a drive or UNC volume in which case ensure there
4747 is a trailing separator. */
4748 len
= strlen (name
);
4749 name
= strcpy (alloca (len
+ 2), name
);
4751 /* Avoid a somewhat costly call to is_symlink if the filesystem
4752 doesn't support symlinks. */
4753 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4754 is_a_symlink
= is_symlink (name
);
4756 /* Plan A: Open the file and get all the necessary information via
4757 the resulting handle. This solves several issues in one blow:
4759 . retrieves attributes for the target of a symlink, if needed
4760 . gets attributes of root directories and symlinks pointing to
4761 root directories, thus avoiding the need for special-casing
4762 these and detecting them by examining the file-name format
4763 . retrieves more accurate attributes (e.g., non-zero size for
4764 some directories, esp. directories that are junction points)
4765 . correctly resolves "c:/..", "/.." and similar file names
4766 . avoids run-time penalties for 99% of use cases
4768 Plan A is always tried first, unless the user asked not to (but
4769 if the file is a symlink and we need to follow links, we try Plan
4770 A even if the user asked not to).
4772 If Plan A fails, we go to Plan B (below), where various
4773 potentially expensive techniques must be used to handle "special"
4774 files such as UNC volumes etc. */
4775 if (!(NILP (Vw32_get_true_file_attributes
)
4776 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4777 /* Following symlinks requires getting the info by handle. */
4778 || (is_a_symlink
&& follow_symlinks
))
4780 BY_HANDLE_FILE_INFORMATION info
;
4782 if (is_a_symlink
&& !follow_symlinks
)
4783 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4784 /* READ_CONTROL access rights are required to get security info
4785 by handle. But if the OS doesn't support security in the
4786 first place, we don't need to try. */
4787 if (is_windows_9x () != TRUE
)
4788 access_rights
|= READ_CONTROL
;
4790 if (w32_unicode_filenames
)
4792 filename_to_utf16 (name
, name_w
);
4793 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4795 /* If CreateFile fails with READ_CONTROL, try again with
4796 zero as access rights. */
4797 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4798 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4803 filename_to_ansi (name
, name_a
);
4804 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4806 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4807 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4810 if (fh
== INVALID_HANDLE_VALUE
)
4811 goto no_true_file_attributes
;
4813 /* This is more accurate in terms of getting the correct number
4814 of links, but is quite slow (it is noticeable when Emacs is
4815 making a list of file name completions). */
4816 if (GetFileInformationByHandle (fh
, &info
))
4818 nlinks
= info
.nNumberOfLinks
;
4819 /* Might as well use file index to fake inode values, but this
4820 is not guaranteed to be unique unless we keep a handle open
4821 all the time (even then there are situations where it is
4822 not unique). Reputedly, there are at most 48 bits of info
4823 (on NTFS, presumably less on FAT). */
4824 fake_inode
= info
.nFileIndexHigh
;
4826 fake_inode
+= info
.nFileIndexLow
;
4827 serialnum
= info
.dwVolumeSerialNumber
;
4828 fs_high
= info
.nFileSizeHigh
;
4829 fs_low
= info
.nFileSizeLow
;
4830 ctime
= info
.ftCreationTime
;
4831 atime
= info
.ftLastAccessTime
;
4832 wtime
= info
.ftLastWriteTime
;
4833 fattrs
= info
.dwFileAttributes
;
4837 /* We don't go to Plan B here, because it's not clear that
4838 it's a good idea. The only known use case where
4839 CreateFile succeeds, but GetFileInformationByHandle fails
4840 (with ERROR_INVALID_FUNCTION) is for character devices
4841 such as NUL, PRN, etc. For these, switching to Plan B is
4842 a net loss, because we lose the character device
4843 attribute returned by GetFileType below (FindFirstFile
4844 doesn't set that bit in the attributes), and the other
4845 fields don't make sense for character devices anyway.
4846 Emacs doesn't really care for non-file entities in the
4847 context of l?stat, so neither do we. */
4849 /* w32err is assigned so one could put a breakpoint here and
4850 examine its value, when GetFileInformationByHandle
4852 DWORD w32err
= GetLastError ();
4856 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4862 /* Test for a symlink before testing for a directory, since
4863 symlinks to directories have the directory bit set, but we
4864 don't want them to appear as directories. */
4865 if (is_a_symlink
&& !follow_symlinks
)
4866 buf
->st_mode
= S_IFLNK
;
4867 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4868 buf
->st_mode
= S_IFDIR
;
4871 DWORD ftype
= GetFileType (fh
);
4875 case FILE_TYPE_DISK
:
4876 buf
->st_mode
= S_IFREG
;
4878 case FILE_TYPE_PIPE
:
4879 buf
->st_mode
= S_IFIFO
;
4881 case FILE_TYPE_CHAR
:
4882 case FILE_TYPE_UNKNOWN
:
4884 buf
->st_mode
= S_IFCHR
;
4887 /* We produce the fallback owner and group data, based on the
4888 current user that runs Emacs, in the following cases:
4890 . caller didn't request owner and group info
4891 . this is Windows 9X
4892 . getting security by handle failed, and we need to produce
4893 information for the target of a symlink (this is better
4894 than producing a potentially misleading info about the
4897 If getting security by handle fails, and we don't need to
4898 resolve symlinks, we try getting security by name. */
4899 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4900 get_file_owner_and_group (NULL
, buf
);
4903 psd
= get_file_security_desc_by_handle (fh
);
4906 get_file_owner_and_group (psd
, buf
);
4909 else if (!(is_a_symlink
&& follow_symlinks
))
4911 psd
= get_file_security_desc_by_name (name
);
4912 get_file_owner_and_group (psd
, buf
);
4916 get_file_owner_and_group (NULL
, buf
);
4922 no_true_file_attributes
:
4923 /* Plan B: Either getting a handle on the file failed, or the
4924 caller explicitly asked us to not bother making this
4925 information more accurate.
4927 Implementation note: In Plan B, we never bother to resolve
4928 symlinks, even if we got here because we tried Plan A and
4929 failed. That's because, even if the caller asked for extra
4930 precision by setting Vw32_get_true_file_attributes to t,
4931 resolving symlinks requires acquiring a file handle to the
4932 symlink, which we already know will fail. And if the user
4933 did not ask for extra precision, resolving symlinks will fly
4934 in the face of that request, since the user then wants the
4935 lightweight version of the code. */
4936 rootdir
= (path
>= save_name
+ len
- 1
4937 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4939 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4940 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4941 if (IS_DIRECTORY_SEP (r
[0])
4942 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4945 /* Note: If NAME is a symlink to the root of a UNC volume
4946 (i.e. "\\SERVER"), we will not detect that here, and we will
4947 return data about the symlink as result of FindFirst below.
4948 This is unfortunate, but that marginal use case does not
4949 justify a call to chase_symlinks which would impose a penalty
4950 on all the other use cases. (We get here for symlinks to
4951 roots of UNC volumes because CreateFile above fails for them,
4952 unlike with symlinks to root directories X:\ of drives.) */
4953 if (is_unc_volume (name
))
4955 fattrs
= unc_volume_file_attributes (name
);
4959 ctime
= atime
= wtime
= utc_base_ft
;
4963 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4964 strcat (name
, "\\");
4965 if (GetDriveType (name
) < 2)
4971 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4972 ctime
= atime
= wtime
= utc_base_ft
;
4978 if (IS_DIRECTORY_SEP (name
[len
-1]))
4981 /* (This is hacky, but helps when doing file completions on
4982 network drives.) Optimize by using information available from
4983 active readdir if possible. */
4984 len
= strlen (dir_pathname
);
4985 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4987 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4988 && last_dir_find_data
!= -1
4989 && !(is_a_symlink
&& follow_symlinks
)
4990 /* The 2 file-name comparisons below support only ASCII
4991 characters, and will lose (compare not equal) when
4992 the file names include non-ASCII characters that are
4993 the same but for the case. However, doing this
4994 properly involves: (a) converting both file names to
4995 UTF-16, (b) lower-casing both names using CharLowerW,
4996 and (c) comparing the results; this would be quite a
4997 bit slower, whereas Plan B is for users who want
4998 lightweight albeit inaccurate version of 'stat'. */
4999 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5000 && IS_DIRECTORY_SEP (name
[len
])
5001 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5003 have_wfd
= last_dir_find_data
;
5004 /* This was the last entry returned by readdir. */
5005 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5006 wfd_w
= dir_find_data_w
;
5008 wfd_a
= dir_find_data_a
;
5012 logon_network_drive (name
);
5014 if (w32_unicode_filenames
)
5016 filename_to_utf16 (name
, name_w
);
5017 fh
= FindFirstFileW (name_w
, &wfd_w
);
5018 have_wfd
= DIR_FIND_DATA_W
;
5022 filename_to_ansi (name
, name_a
);
5023 /* If NAME includes characters not representable by
5024 the current ANSI codepage, filename_to_ansi
5025 usually replaces them with a '?'. We don't want
5026 to let FindFirstFileA interpret those as wildcards,
5027 and "succeed", returning us data from some random
5028 file in the same directory. */
5029 if (_mbspbrk (name_a
, "?"))
5030 fh
= INVALID_HANDLE_VALUE
;
5032 fh
= FindFirstFileA (name_a
, &wfd_a
);
5033 have_wfd
= DIR_FIND_DATA_A
;
5035 if (fh
== INVALID_HANDLE_VALUE
)
5042 /* Note: if NAME is a symlink, the information we get from
5043 FindFirstFile is for the symlink, not its target. */
5044 if (have_wfd
== DIR_FIND_DATA_W
)
5046 fattrs
= wfd_w
.dwFileAttributes
;
5047 ctime
= wfd_w
.ftCreationTime
;
5048 atime
= wfd_w
.ftLastAccessTime
;
5049 wtime
= wfd_w
.ftLastWriteTime
;
5050 fs_high
= wfd_w
.nFileSizeHigh
;
5051 fs_low
= wfd_w
.nFileSizeLow
;
5055 fattrs
= wfd_a
.dwFileAttributes
;
5056 ctime
= wfd_a
.ftCreationTime
;
5057 atime
= wfd_a
.ftLastAccessTime
;
5058 wtime
= wfd_a
.ftLastWriteTime
;
5059 fs_high
= wfd_a
.nFileSizeHigh
;
5060 fs_low
= wfd_a
.nFileSizeLow
;
5064 serialnum
= volume_info
.serialnum
;
5066 if (is_a_symlink
&& !follow_symlinks
)
5067 buf
->st_mode
= S_IFLNK
;
5068 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5069 buf
->st_mode
= S_IFDIR
;
5071 buf
->st_mode
= S_IFREG
;
5073 get_file_owner_and_group (NULL
, buf
);
5076 buf
->st_ino
= fake_inode
;
5078 buf
->st_dev
= serialnum
;
5079 buf
->st_rdev
= serialnum
;
5081 buf
->st_size
= fs_high
;
5082 buf
->st_size
<<= 32;
5083 buf
->st_size
+= fs_low
;
5084 buf
->st_nlink
= nlinks
;
5086 /* Convert timestamps to Unix format. */
5087 buf
->st_mtime
= convert_time (wtime
);
5088 buf
->st_atime
= convert_time (atime
);
5089 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5090 buf
->st_ctime
= convert_time (ctime
);
5091 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5093 /* determine rwx permissions */
5094 if (is_a_symlink
&& !follow_symlinks
)
5095 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5098 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5099 permission
= S_IREAD
;
5101 permission
= S_IREAD
| S_IWRITE
;
5103 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5104 permission
|= S_IEXEC
;
5105 else if (is_exec (name
))
5106 permission
|= S_IEXEC
;
5109 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5115 stat (const char * path
, struct stat
* buf
)
5117 return stat_worker (path
, buf
, 1);
5121 lstat (const char * path
, struct stat
* buf
)
5123 return stat_worker (path
, buf
, 0);
5127 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5129 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5130 This is good enough for the current usage in Emacs, but is fragile.
5132 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5133 Gnulib does this and can serve as a model. */
5134 char fullname
[MAX_UTF8_PATH
];
5138 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5141 errno
= ENAMETOOLONG
;
5147 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5150 /* Provide fstat and utime as well as stat for consistent handling of
5153 fstat (int desc
, struct stat
* buf
)
5155 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5156 BY_HANDLE_FILE_INFORMATION info
;
5157 unsigned __int64 fake_inode
;
5160 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5162 case FILE_TYPE_DISK
:
5163 buf
->st_mode
= S_IFREG
;
5164 if (!GetFileInformationByHandle (fh
, &info
))
5170 case FILE_TYPE_PIPE
:
5171 buf
->st_mode
= S_IFIFO
;
5173 case FILE_TYPE_CHAR
:
5174 case FILE_TYPE_UNKNOWN
:
5176 buf
->st_mode
= S_IFCHR
;
5178 memset (&info
, 0, sizeof (info
));
5179 info
.dwFileAttributes
= 0;
5180 info
.ftCreationTime
= utc_base_ft
;
5181 info
.ftLastAccessTime
= utc_base_ft
;
5182 info
.ftLastWriteTime
= utc_base_ft
;
5185 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5186 buf
->st_mode
= S_IFDIR
;
5188 buf
->st_nlink
= info
.nNumberOfLinks
;
5189 /* Might as well use file index to fake inode values, but this
5190 is not guaranteed to be unique unless we keep a handle open
5191 all the time (even then there are situations where it is
5192 not unique). Reputedly, there are at most 48 bits of info
5193 (on NTFS, presumably less on FAT). */
5194 fake_inode
= info
.nFileIndexHigh
;
5196 fake_inode
+= info
.nFileIndexLow
;
5198 /* MSVC defines _ino_t to be short; other libc's might not. */
5199 if (sizeof (buf
->st_ino
) == 2)
5200 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5202 buf
->st_ino
= fake_inode
;
5204 /* If the caller so requested, get the true file owner and group.
5205 Otherwise, consider the file to belong to the current user. */
5206 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5207 get_file_owner_and_group (NULL
, buf
);
5210 PSECURITY_DESCRIPTOR psd
= NULL
;
5212 psd
= get_file_security_desc_by_handle (fh
);
5215 get_file_owner_and_group (psd
, buf
);
5219 get_file_owner_and_group (NULL
, buf
);
5222 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5223 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5225 buf
->st_size
= info
.nFileSizeHigh
;
5226 buf
->st_size
<<= 32;
5227 buf
->st_size
+= info
.nFileSizeLow
;
5229 /* Convert timestamps to Unix format. */
5230 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5231 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5232 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5233 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5234 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5236 /* determine rwx permissions */
5237 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5238 permission
= S_IREAD
;
5240 permission
= S_IREAD
| S_IWRITE
;
5242 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5243 permission
|= S_IEXEC
;
5246 #if 0 /* no way of knowing the filename */
5247 char * p
= strrchr (name
, '.');
5249 (xstrcasecmp (p
, ".exe") == 0 ||
5250 xstrcasecmp (p
, ".com") == 0 ||
5251 xstrcasecmp (p
, ".bat") == 0 ||
5252 xstrcasecmp (p
, ".cmd") == 0))
5253 permission
|= S_IEXEC
;
5257 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5262 /* A version of 'utime' which handles directories as well as
5266 utime (const char *name
, struct utimbuf
*times
)
5268 struct utimbuf deftime
;
5275 deftime
.modtime
= deftime
.actime
= time (NULL
);
5279 if (w32_unicode_filenames
)
5281 wchar_t name_utf16
[MAX_PATH
];
5283 if (filename_to_utf16 (name
, name_utf16
) != 0)
5284 return -1; /* errno set by filename_to_utf16 */
5286 /* Need write access to set times. */
5287 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5288 /* If NAME specifies a directory, FILE_SHARE_DELETE
5289 allows other processes to delete files inside it,
5290 while we have the directory open. */
5291 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5292 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5296 char name_ansi
[MAX_PATH
];
5298 if (filename_to_ansi (name
, name_ansi
) != 0)
5299 return -1; /* errno set by filename_to_ansi */
5301 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5302 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5303 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5305 if (fh
!= INVALID_HANDLE_VALUE
)
5307 convert_from_time_t (times
->actime
, &atime
);
5308 convert_from_time_t (times
->modtime
, &mtime
);
5309 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5319 DWORD err
= GetLastError ();
5323 case ERROR_FILE_NOT_FOUND
:
5324 case ERROR_PATH_NOT_FOUND
:
5325 case ERROR_INVALID_DRIVE
:
5326 case ERROR_BAD_NETPATH
:
5327 case ERROR_DEV_NOT_EXIST
:
5328 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5329 file name includes ?s, i.e. translation to ANSI failed. */
5330 case ERROR_INVALID_NAME
:
5333 case ERROR_TOO_MANY_OPEN_FILES
:
5336 case ERROR_ACCESS_DENIED
:
5337 case ERROR_SHARING_VIOLATION
:
5349 /* Emacs expects us to support the traditional octal form of the mode
5350 bits, which is not what msvcrt.dll wants. */
5352 #define WRITE_USER 00200
5355 sys_umask (int mode
)
5357 static int current_mask
;
5358 int retval
, arg
= 0;
5360 /* The only bit we really support is the write bit. Files are
5361 always readable on MS-Windows, and the execute bit does not exist
5363 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5364 to prevent access by other users on NTFS. */
5365 if ((mode
& WRITE_USER
) != 0)
5368 retval
= _umask (arg
);
5369 /* Merge into the return value the bits they've set the last time,
5370 which msvcrt.dll ignores and never returns. Emacs insists on its
5371 notion of mask being identical to what we return. */
5372 retval
|= (current_mask
& ~WRITE_USER
);
5373 current_mask
= mode
;
5379 /* Symlink-related functions. */
5380 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5381 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5385 symlink (char const *filename
, char const *linkname
)
5387 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5389 int dir_access
, filename_ends_in_slash
;
5391 /* Diagnostics follows Posix as much as possible. */
5392 if (filename
== NULL
|| linkname
== NULL
)
5402 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5404 errno
= ENAMETOOLONG
;
5408 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5409 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5415 /* Note: since empty FILENAME was already rejected, we can safely
5416 refer to FILENAME[1]. */
5417 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5419 /* Non-absolute FILENAME is understood as being relative to
5420 LINKNAME's directory. We need to prepend that directory to
5421 FILENAME to get correct results from faccessat below, since
5422 otherwise it will interpret FILENAME relative to the
5423 directory where the Emacs process runs. Note that
5424 make-symbolic-link always makes sure LINKNAME is a fully
5425 expanded file name. */
5426 char tem
[MAX_UTF8_PATH
];
5427 char *p
= linkfn
+ strlen (linkfn
);
5429 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5432 strncpy (tem
, linkfn
, p
- linkfn
);
5433 tem
[p
- linkfn
] = '\0';
5434 strcat (tem
, filename
);
5435 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5438 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5440 /* Since Windows distinguishes between symlinks to directories and
5441 to files, we provide a kludgy feature: if FILENAME doesn't
5442 exist, but ends in a slash, we create a symlink to directory. If
5443 FILENAME exists and is a directory, we always create a symlink to
5445 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5446 if (dir_access
== 0 || filename_ends_in_slash
)
5447 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5449 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5450 if (filename_ends_in_slash
)
5451 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5454 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5456 /* ENOSYS is set by create_symbolic_link, when it detects that
5457 the OS doesn't support the CreateSymbolicLink API. */
5458 if (errno
!= ENOSYS
)
5460 DWORD w32err
= GetLastError ();
5464 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5465 TGTFN point to the same file name, go figure. */
5467 case ERROR_FILE_EXISTS
:
5470 case ERROR_ACCESS_DENIED
:
5473 case ERROR_FILE_NOT_FOUND
:
5474 case ERROR_PATH_NOT_FOUND
:
5475 case ERROR_BAD_NETPATH
:
5476 case ERROR_INVALID_REPARSE_DATA
:
5479 case ERROR_DIRECTORY
:
5482 case ERROR_PRIVILEGE_NOT_HELD
:
5483 case ERROR_NOT_ALL_ASSIGNED
:
5486 case ERROR_DISK_FULL
:
5499 /* A quick inexpensive test of whether FILENAME identifies a file that
5500 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5501 must already be in the normalized form returned by
5504 Note: for repeated operations on many files, it is best to test
5505 whether the underlying volume actually supports symlinks, by
5506 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5507 avoid the call to this function if it doesn't. That's because the
5508 call to GetFileAttributes takes a non-negligible time, especially
5509 on non-local or removable filesystems. See stat_worker for an
5510 example of how to do that. */
5512 is_symlink (const char *filename
)
5515 wchar_t filename_w
[MAX_PATH
];
5516 char filename_a
[MAX_PATH
];
5517 WIN32_FIND_DATAW wfdw
;
5518 WIN32_FIND_DATAA wfda
;
5520 int attrs_mean_symlink
;
5522 if (w32_unicode_filenames
)
5524 filename_to_utf16 (filename
, filename_w
);
5525 attrs
= GetFileAttributesW (filename_w
);
5529 filename_to_ansi (filename
, filename_a
);
5530 attrs
= GetFileAttributesA (filename_a
);
5534 DWORD w32err
= GetLastError ();
5538 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5540 case ERROR_ACCESS_DENIED
:
5543 case ERROR_FILE_NOT_FOUND
:
5544 case ERROR_PATH_NOT_FOUND
:
5551 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5553 logon_network_drive (filename
);
5554 if (w32_unicode_filenames
)
5556 fh
= FindFirstFileW (filename_w
, &wfdw
);
5557 attrs_mean_symlink
=
5558 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5559 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5561 else if (_mbspbrk (filename_a
, "?"))
5563 /* filename_to_ansi failed to convert the file name. */
5569 fh
= FindFirstFileA (filename_a
, &wfda
);
5570 attrs_mean_symlink
=
5571 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5572 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5574 if (fh
== INVALID_HANDLE_VALUE
)
5577 return attrs_mean_symlink
;
5580 /* If NAME identifies a symbolic link, copy into BUF the file name of
5581 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5582 null-terminate the target name, even if it fits. Return the number
5583 of bytes copied, or -1 if NAME is not a symlink or any error was
5584 encountered while resolving it. The file name copied into BUF is
5585 encoded in the current ANSI codepage. */
5587 readlink (const char *name
, char *buf
, size_t buf_size
)
5590 TOKEN_PRIVILEGES privs
;
5591 int restore_privs
= 0;
5594 char resolved
[MAX_UTF8_PATH
];
5607 path
= map_w32_filename (name
, NULL
);
5609 if (strlen (path
) > MAX_UTF8_PATH
)
5611 errno
= ENAMETOOLONG
;
5616 if (is_windows_9x () == TRUE
5617 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5618 || !is_symlink (path
))
5621 errno
= EINVAL
; /* not a symlink */
5625 /* Done with simple tests, now we're in for some _real_ work. */
5626 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5628 /* Implementation note: From here and onward, don't return early,
5629 since that will fail to restore the original set of privileges of
5630 the calling thread. */
5632 retval
= -1; /* not too optimistic, are we? */
5634 /* Note: In the next call to CreateFile, we use zero as the 2nd
5635 argument because, when the symlink is a hidden/system file,
5636 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5637 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5638 and directory symlinks. */
5639 if (w32_unicode_filenames
)
5641 wchar_t path_w
[MAX_PATH
];
5643 filename_to_utf16 (path
, path_w
);
5644 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5645 FILE_FLAG_OPEN_REPARSE_POINT
5646 | FILE_FLAG_BACKUP_SEMANTICS
,
5651 char path_a
[MAX_PATH
];
5653 filename_to_ansi (path
, path_a
);
5654 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5655 FILE_FLAG_OPEN_REPARSE_POINT
5656 | FILE_FLAG_BACKUP_SEMANTICS
,
5659 if (sh
!= INVALID_HANDLE_VALUE
)
5661 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5662 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5665 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5666 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5669 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5673 /* Copy the link target name, in wide characters, from
5674 reparse_data, then convert it to multibyte encoding in
5675 the current locale's codepage. */
5679 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5681 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5682 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5683 size_t size_to_copy
= buf_size
;
5685 /* According to MSDN, PrintNameLength does not include the
5686 terminating null character. */
5687 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5688 memcpy (lwname
, lwname_src
, lwname_len
);
5689 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5690 filename_from_utf16 (lwname
, resolved
);
5691 dostounix_filename (resolved
);
5692 lname_size
= strlen (resolved
) + 1;
5693 if (lname_size
<= buf_size
)
5694 size_to_copy
= lname_size
;
5695 strncpy (buf
, resolved
, size_to_copy
);
5697 retval
= size_to_copy
;
5703 /* CreateFile failed. */
5704 DWORD w32err2
= GetLastError ();
5708 case ERROR_FILE_NOT_FOUND
:
5709 case ERROR_PATH_NOT_FOUND
:
5712 case ERROR_ACCESS_DENIED
:
5713 case ERROR_TOO_MANY_OPEN_FILES
:
5723 restore_privilege (&privs
);
5731 readlinkat (int fd
, char const *name
, char *buffer
,
5734 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5735 as in fstatat. FIXME: Add proper support for readlinkat. */
5736 char fullname
[MAX_UTF8_PATH
];
5740 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5743 errno
= ENAMETOOLONG
;
5749 return readlink (name
, buffer
, buffer_size
);
5752 /* If FILE is a symlink, return its target (stored in a static
5753 buffer); otherwise return FILE.
5755 This function repeatedly resolves symlinks in the last component of
5756 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5757 until it arrives at a file whose last component is not a symlink,
5758 or some error occurs. It returns the target of the last
5759 successfully resolved symlink in the chain. If it succeeds to
5760 resolve even a single symlink, the value returned is an absolute
5761 file name with backslashes (result of GetFullPathName). By
5762 contrast, if the original FILE is returned, it is unaltered.
5764 Note: This function can set errno even if it succeeds.
5766 Implementation note: we only resolve the last portion ("basename")
5767 of the argument FILE and of each following file in the chain,
5768 disregarding any possible symlinks in its leading directories.
5769 This is because Windows system calls and library functions
5770 transparently resolve symlinks in leading directories and return
5771 correct information, as long as the basename is not a symlink. */
5773 chase_symlinks (const char *file
)
5775 static char target
[MAX_UTF8_PATH
];
5776 char link
[MAX_UTF8_PATH
];
5777 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5778 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5779 ssize_t res
, link_len
;
5782 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5783 return (char *)file
;
5785 if (w32_unicode_filenames
)
5787 wchar_t file_w
[MAX_PATH
];
5789 filename_to_utf16 (file
, file_w
);
5790 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5791 return (char *)file
;
5792 filename_from_utf16 (link_w
, link
);
5796 char file_a
[MAX_PATH
];
5798 filename_to_ansi (file
, file_a
);
5799 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5800 return (char *)file
;
5801 filename_from_ansi (link_a
, link
);
5803 link_len
= strlen (link
);
5808 /* Remove trailing slashes, as we want to resolve the last
5809 non-trivial part of the link name. */
5810 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5811 link
[link_len
--] = '\0';
5813 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5817 if (!(IS_DEVICE_SEP (target
[1])
5818 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5820 /* Target is relative. Append it to the directory part of
5821 the symlink, then copy the result back to target. */
5822 char *p
= link
+ link_len
;
5824 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5827 strcpy (target
, link
);
5829 /* Resolve any "." and ".." to get a fully-qualified file name
5831 if (w32_unicode_filenames
)
5833 filename_to_utf16 (target
, target_w
);
5834 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5836 filename_from_utf16 (link_w
, link
);
5840 filename_to_ansi (target
, target_a
);
5841 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5843 filename_from_ansi (link_a
, link
);
5845 link_len
= strlen (link
);
5847 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5849 if (loop_count
> 100)
5852 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5853 return (char *)file
;
5858 /* Posix ACL emulation. */
5861 acl_valid (acl_t acl
)
5863 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5867 acl_to_text (acl_t acl
, ssize_t
*size
)
5870 SECURITY_INFORMATION flags
=
5871 OWNER_SECURITY_INFORMATION
|
5872 GROUP_SECURITY_INFORMATION
|
5873 DACL_SECURITY_INFORMATION
;
5874 char *retval
= NULL
;
5880 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5883 /* We don't want to mix heaps, so we duplicate the string in our
5884 heap and free the one allocated by the API. */
5885 retval
= xstrdup (str_acl
);
5888 LocalFree (str_acl
);
5890 else if (errno
!= ENOTSUP
)
5897 acl_from_text (const char *acl_str
)
5899 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5905 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5908 retval
= xmalloc (sd_size
);
5909 memcpy (retval
, psd
, sd_size
);
5912 else if (errno
!= ENOTSUP
)
5919 acl_free (void *ptr
)
5926 acl_get_file (const char *fname
, acl_type_t type
)
5928 PSECURITY_DESCRIPTOR psd
= NULL
;
5929 const char *filename
;
5931 if (type
== ACL_TYPE_ACCESS
)
5934 SECURITY_INFORMATION si
=
5935 OWNER_SECURITY_INFORMATION
|
5936 GROUP_SECURITY_INFORMATION
|
5937 DACL_SECURITY_INFORMATION
;
5940 filename
= map_w32_filename (fname
, NULL
);
5941 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5942 fname
= chase_symlinks (filename
);
5947 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5948 && errno
!= ENOTSUP
)
5950 err
= GetLastError ();
5951 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5953 psd
= xmalloc (sd_len
);
5954 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5961 else if (err
== ERROR_FILE_NOT_FOUND
5962 || err
== ERROR_PATH_NOT_FOUND
5963 /* ERROR_INVALID_NAME is what we get if
5964 w32-unicode-filenames is nil and the file cannot
5965 be encoded in the current ANSI codepage. */
5966 || err
== ERROR_INVALID_NAME
)
5974 else if (type
!= ACL_TYPE_DEFAULT
)
5981 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5983 TOKEN_PRIVILEGES old1
, old2
;
5985 int st
= 0, retval
= -1;
5986 SECURITY_INFORMATION flags
= 0;
5987 PSID psidOwner
, psidGroup
;
5992 const char *filename
;
5994 if (acl_valid (acl
) != 0
5995 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6001 if (type
== ACL_TYPE_DEFAULT
)
6007 filename
= map_w32_filename (fname
, NULL
);
6008 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6009 fname
= chase_symlinks (filename
);
6013 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6016 flags
|= OWNER_SECURITY_INFORMATION
;
6017 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6020 flags
|= GROUP_SECURITY_INFORMATION
;
6021 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6024 flags
|= DACL_SECURITY_INFORMATION
;
6028 /* According to KB-245153, setting the owner will succeed if either:
6029 (1) the caller is the user who will be the new owner, and has the
6030 SE_TAKE_OWNERSHIP privilege, or
6031 (2) the caller has the SE_RESTORE privilege, in which case she can
6032 set any valid user or group as the owner
6034 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6035 privileges, and disregard any failures in obtaining them. If
6036 these privileges cannot be obtained, and do not already exist in
6037 the calling thread's security token, this function could fail
6039 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6041 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6046 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6047 DACL inheritance is involved, but it seems to preserve ownership
6048 better than SetNamedSecurityInfo, which is important e.g., in
6050 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6052 err
= GetLastError ();
6054 if (errno
!= ENOTSUP
)
6055 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6056 psidOwner
, psidGroup
, pacl
, NULL
);
6059 err
= ERROR_SUCCESS
;
6060 if (err
!= ERROR_SUCCESS
)
6062 if (errno
== ENOTSUP
)
6064 else if (err
== ERROR_INVALID_OWNER
6065 || err
== ERROR_NOT_ALL_ASSIGNED
6066 || err
== ERROR_ACCESS_DENIED
)
6068 /* Maybe the requested ACL and the one the file already has
6069 are identical, in which case we can silently ignore the
6070 failure. (And no, Windows doesn't.) */
6071 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6076 char *acl_from
= acl_to_text (current_acl
, NULL
);
6077 char *acl_to
= acl_to_text (acl
, NULL
);
6079 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6085 acl_free (acl_from
);
6088 acl_free (current_acl
);
6091 else if (err
== ERROR_FILE_NOT_FOUND
6092 || err
== ERROR_PATH_NOT_FOUND
6093 /* ERROR_INVALID_NAME is what we get if
6094 w32-unicode-filenames is nil and the file cannot be
6095 encoded in the current ANSI codepage. */
6096 || err
== ERROR_INVALID_NAME
)
6110 restore_privilege (&old2
);
6111 restore_privilege (&old1
);
6119 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6120 have a fixed max size for file names, so we don't need the kind of
6121 alloc/malloc/realloc dance the gnulib version does. We also don't
6122 support FD-relative symlinks. */
6124 careadlinkat (int fd
, char const *filename
,
6125 char *buffer
, size_t buffer_size
,
6126 struct allocator
const *alloc
,
6127 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6129 char linkname
[MAX_UTF8_PATH
];
6132 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6136 char *retval
= buffer
;
6138 linkname
[link_size
++] = '\0';
6139 if (link_size
> buffer_size
)
6140 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6142 memcpy (retval
, linkname
, link_size
);
6150 w32_copy_file (const char *from
, const char *to
,
6151 int keep_time
, int preserve_ownership
, int copy_acls
)
6155 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6156 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6158 /* We ignore preserve_ownership for now. */
6159 preserve_ownership
= preserve_ownership
;
6163 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6164 if (acl
== NULL
&& acl_errno_valid (errno
))
6167 if (w32_unicode_filenames
)
6169 filename_to_utf16 (from
, from_w
);
6170 filename_to_utf16 (to
, to_w
);
6171 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6175 filename_to_ansi (from
, from_a
);
6176 filename_to_ansi (to
, to_a
);
6177 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6181 /* CopyFile doesn't set errno when it fails. By far the most
6182 "popular" reason is that the target is read-only. */
6183 DWORD err
= GetLastError ();
6187 case ERROR_FILE_NOT_FOUND
:
6190 case ERROR_ACCESS_DENIED
:
6193 case ERROR_ENCRYPTION_FAILED
:
6205 /* CopyFile retains the timestamp by default. However, see
6206 "Community Additions" for CopyFile: it sounds like that is not
6207 entirely true. Testing on Windows XP confirms that modified time
6208 is copied, but creation and last-access times are not.
6210 else if (!keep_time
)
6212 struct timespec now
;
6215 if (w32_unicode_filenames
)
6217 /* Ensure file is writable while its times are set. */
6218 attributes
= GetFileAttributesW (to_w
);
6219 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6220 now
= current_timespec ();
6221 if (set_file_times (-1, to
, now
, now
))
6223 /* Restore original attributes. */
6224 SetFileAttributesW (to_w
, attributes
);
6229 /* Restore original attributes. */
6230 SetFileAttributesW (to_w
, attributes
);
6234 attributes
= GetFileAttributesA (to_a
);
6235 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6236 now
= current_timespec ();
6237 if (set_file_times (-1, to
, now
, now
))
6239 SetFileAttributesA (to_a
, attributes
);
6244 SetFileAttributesA (to_a
, attributes
);
6250 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6252 if (fail
&& acl_errno_valid (errno
))
6260 /* Support for browsing other processes and their attributes. See
6261 process.c for the Lisp bindings. */
6263 /* Helper wrapper functions. */
6265 static HANDLE WINAPI
6266 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6268 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6270 if (g_b_init_create_toolhelp32_snapshot
== 0)
6272 g_b_init_create_toolhelp32_snapshot
= 1;
6273 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6274 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6275 "CreateToolhelp32Snapshot");
6277 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6279 return INVALID_HANDLE_VALUE
;
6281 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6285 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6287 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6289 if (g_b_init_process32_first
== 0)
6291 g_b_init_process32_first
= 1;
6292 s_pfn_Process32_First
= (Process32First_Proc
)
6293 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6296 if (s_pfn_Process32_First
== NULL
)
6300 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6304 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6306 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6308 if (g_b_init_process32_next
== 0)
6310 g_b_init_process32_next
= 1;
6311 s_pfn_Process32_Next
= (Process32Next_Proc
)
6312 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6315 if (s_pfn_Process32_Next
== NULL
)
6319 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6323 open_thread_token (HANDLE ThreadHandle
,
6324 DWORD DesiredAccess
,
6326 PHANDLE TokenHandle
)
6328 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6329 HMODULE hm_advapi32
= NULL
;
6330 if (is_windows_9x () == TRUE
)
6332 SetLastError (ERROR_NOT_SUPPORTED
);
6335 if (g_b_init_open_thread_token
== 0)
6337 g_b_init_open_thread_token
= 1;
6338 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6339 s_pfn_Open_Thread_Token
=
6340 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6342 if (s_pfn_Open_Thread_Token
== NULL
)
6344 SetLastError (ERROR_NOT_SUPPORTED
);
6348 s_pfn_Open_Thread_Token (
6357 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6359 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6360 HMODULE hm_advapi32
= NULL
;
6361 if (is_windows_9x () == TRUE
)
6365 if (g_b_init_impersonate_self
== 0)
6367 g_b_init_impersonate_self
= 1;
6368 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6369 s_pfn_Impersonate_Self
=
6370 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6372 if (s_pfn_Impersonate_Self
== NULL
)
6376 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6380 revert_to_self (void)
6382 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6383 HMODULE hm_advapi32
= NULL
;
6384 if (is_windows_9x () == TRUE
)
6388 if (g_b_init_revert_to_self
== 0)
6390 g_b_init_revert_to_self
= 1;
6391 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6392 s_pfn_Revert_To_Self
=
6393 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6395 if (s_pfn_Revert_To_Self
== NULL
)
6399 return s_pfn_Revert_To_Self ();
6403 get_process_memory_info (HANDLE h_proc
,
6404 PPROCESS_MEMORY_COUNTERS mem_counters
,
6407 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6408 HMODULE hm_psapi
= NULL
;
6409 if (is_windows_9x () == TRUE
)
6413 if (g_b_init_get_process_memory_info
== 0)
6415 g_b_init_get_process_memory_info
= 1;
6416 hm_psapi
= LoadLibrary ("Psapi.dll");
6418 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6419 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6421 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6425 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6429 get_process_working_set_size (HANDLE h_proc
,
6433 static GetProcessWorkingSetSize_Proc
6434 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6436 if (is_windows_9x () == TRUE
)
6440 if (g_b_init_get_process_working_set_size
== 0)
6442 g_b_init_get_process_working_set_size
= 1;
6443 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6444 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6445 "GetProcessWorkingSetSize");
6447 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6451 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6455 global_memory_status (MEMORYSTATUS
*buf
)
6457 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6459 if (is_windows_9x () == TRUE
)
6463 if (g_b_init_global_memory_status
== 0)
6465 g_b_init_global_memory_status
= 1;
6466 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6467 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6468 "GlobalMemoryStatus");
6470 if (s_pfn_Global_Memory_Status
== NULL
)
6474 return s_pfn_Global_Memory_Status (buf
);
6478 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6480 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6482 if (is_windows_9x () == TRUE
)
6486 if (g_b_init_global_memory_status_ex
== 0)
6488 g_b_init_global_memory_status_ex
= 1;
6489 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6490 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6491 "GlobalMemoryStatusEx");
6493 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6497 return s_pfn_Global_Memory_Status_Ex (buf
);
6501 list_system_processes (void)
6503 struct gcpro gcpro1
;
6504 Lisp_Object proclist
= Qnil
;
6507 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6509 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6511 PROCESSENTRY32 proc_entry
;
6517 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6518 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6519 res
= process32_next (h_snapshot
, &proc_entry
))
6521 proc_id
= proc_entry
.th32ProcessID
;
6522 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6525 CloseHandle (h_snapshot
);
6527 proclist
= Fnreverse (proclist
);
6534 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6536 TOKEN_PRIVILEGES priv
;
6537 DWORD priv_size
= sizeof (priv
);
6538 DWORD opriv_size
= sizeof (*old_priv
);
6539 HANDLE h_token
= NULL
;
6540 HANDLE h_thread
= GetCurrentThread ();
6544 res
= open_thread_token (h_thread
,
6545 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6547 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6549 if (impersonate_self (SecurityImpersonation
))
6550 res
= open_thread_token (h_thread
,
6551 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6556 priv
.PrivilegeCount
= 1;
6557 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6558 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6559 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6560 old_priv
, &opriv_size
)
6561 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6565 CloseHandle (h_token
);
6571 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6573 DWORD priv_size
= sizeof (*priv
);
6574 HANDLE h_token
= NULL
;
6577 if (open_thread_token (GetCurrentThread (),
6578 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6581 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6582 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6586 CloseHandle (h_token
);
6592 ltime (ULONGLONG time_100ns
)
6594 ULONGLONG time_sec
= time_100ns
/ 10000000;
6595 int subsec
= time_100ns
% 10000000;
6596 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6597 subsec
/ 10, subsec
% 10 * 100000);
6600 #define U64_TO_LISP_TIME(time) ltime (time)
6603 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6604 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6607 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6608 ULONGLONG tem1
, tem2
, tem3
, tem
;
6611 || !get_process_times_fn
6612 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6613 &ft_kernel
, &ft_user
))
6616 GetSystemTimeAsFileTime (&ft_current
);
6618 FILETIME_TO_U64 (tem1
, ft_kernel
);
6619 *stime
= U64_TO_LISP_TIME (tem1
);
6621 FILETIME_TO_U64 (tem2
, ft_user
);
6622 *utime
= U64_TO_LISP_TIME (tem2
);
6625 *ttime
= U64_TO_LISP_TIME (tem3
);
6627 FILETIME_TO_U64 (tem
, ft_creation
);
6628 /* Process no 4 (System) returns zero creation time. */
6631 *ctime
= U64_TO_LISP_TIME (tem
);
6635 FILETIME_TO_U64 (tem3
, ft_current
);
6636 tem
= (tem3
- utc_base
) - tem
;
6638 *etime
= U64_TO_LISP_TIME (tem
);
6642 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6653 system_process_attributes (Lisp_Object pid
)
6655 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6656 Lisp_Object attrs
= Qnil
;
6657 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6658 HANDLE h_snapshot
, h_proc
;
6661 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6662 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6663 DWORD glength
= sizeof (gname
);
6664 HANDLE token
= NULL
;
6665 SID_NAME_USE user_type
;
6666 unsigned char *buf
= NULL
;
6668 TOKEN_USER user_token
;
6669 TOKEN_PRIMARY_GROUP group_token
;
6672 PROCESS_MEMORY_COUNTERS mem
;
6673 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6674 SIZE_T minrss
, maxrss
;
6676 MEMORY_STATUS_EX memstex
;
6677 double totphys
= 0.0;
6678 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6680 BOOL result
= FALSE
;
6682 CHECK_NUMBER_OR_FLOAT (pid
);
6683 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6685 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6687 GCPRO3 (attrs
, decoded_cmd
, tem
);
6689 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6694 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6695 for (res
= process32_first (h_snapshot
, &pe
); res
;
6696 res
= process32_next (h_snapshot
, &pe
))
6698 if (proc_id
== pe
.th32ProcessID
)
6701 decoded_cmd
= build_string ("Idle");
6704 /* Decode the command name from locale-specific
6706 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6709 code_convert_string_norecord (cmd_str
,
6710 Vlocale_coding_system
, 0);
6712 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6713 attrs
= Fcons (Fcons (Qppid
,
6714 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6716 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6718 attrs
= Fcons (Fcons (Qthcount
,
6719 make_fixnum_or_float (pe
.cntThreads
)),
6726 CloseHandle (h_snapshot
);
6735 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6737 /* If we were denied a handle to the process, try again after
6738 enabling the SeDebugPrivilege in our process. */
6741 TOKEN_PRIVILEGES priv_current
;
6743 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6745 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6747 restore_privilege (&priv_current
);
6753 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6756 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6757 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6759 buf
= xmalloc (blen
);
6760 result
= get_token_information (token
, TokenUser
,
6761 (LPVOID
)buf
, blen
, &needed
);
6764 memcpy (&user_token
, buf
, sizeof (user_token
));
6765 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6767 euid
= get_rid (user_token
.User
.Sid
);
6768 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6773 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6776 strcpy (uname
, "unknown");
6780 ulength
= strlen (uname
);
6786 /* Determine a reasonable euid and gid values. */
6787 if (xstrcasecmp ("administrator", uname
) == 0)
6789 euid
= 500; /* well-known Administrator uid */
6790 egid
= 513; /* well-known None gid */
6794 /* Get group id and name. */
6795 result
= get_token_information (token
, TokenPrimaryGroup
,
6796 (LPVOID
)buf
, blen
, &needed
);
6797 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6799 buf
= xrealloc (buf
, blen
= needed
);
6800 result
= get_token_information (token
, TokenPrimaryGroup
,
6801 (LPVOID
)buf
, blen
, &needed
);
6805 memcpy (&group_token
, buf
, sizeof (group_token
));
6806 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6808 egid
= get_rid (group_token
.PrimaryGroup
);
6809 dlength
= sizeof (domain
);
6811 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6812 gname
, &glength
, NULL
, &dlength
,
6815 w32_add_to_cache (group_token
.PrimaryGroup
,
6819 strcpy (gname
, "None");
6823 glength
= strlen (gname
);
6831 if (!is_windows_9x ())
6833 /* We couldn't open the process token, presumably because of
6834 insufficient access rights. Assume this process is run
6836 strcpy (uname
, "SYSTEM");
6837 strcpy (gname
, "None");
6838 euid
= 18; /* SYSTEM */
6839 egid
= 513; /* None */
6840 glength
= strlen (gname
);
6841 ulength
= strlen (uname
);
6843 /* If we are running under Windows 9X, where security calls are
6844 not supported, we assume all processes are run by the current
6846 else if (GetUserName (uname
, &ulength
))
6848 if (xstrcasecmp ("administrator", uname
) == 0)
6853 strcpy (gname
, "None");
6854 glength
= strlen (gname
);
6855 ulength
= strlen (uname
);
6861 strcpy (uname
, "administrator");
6862 ulength
= strlen (uname
);
6863 strcpy (gname
, "None");
6864 glength
= strlen (gname
);
6867 CloseHandle (token
);
6870 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6871 tem
= make_unibyte_string (uname
, ulength
);
6872 attrs
= Fcons (Fcons (Quser
,
6873 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6875 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6876 tem
= make_unibyte_string (gname
, glength
);
6877 attrs
= Fcons (Fcons (Qgroup
,
6878 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6881 if (global_memory_status_ex (&memstex
))
6882 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6883 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6885 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6886 double, so we need to do this for it... */
6888 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6889 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6890 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6892 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6894 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6895 else if (global_memory_status (&memst
))
6896 totphys
= memst
.dwTotalPhys
/ 1024.0;
6899 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6902 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6904 attrs
= Fcons (Fcons (Qmajflt
,
6905 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6907 attrs
= Fcons (Fcons (Qvsize
,
6908 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6910 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6912 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6915 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6917 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6919 attrs
= Fcons (Fcons (Qmajflt
,
6920 make_fixnum_or_float (mem
.PageFaultCount
)),
6922 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6924 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6927 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6929 DWORD rss
= maxrss
/ 1024;
6931 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6933 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6936 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6938 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6939 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6940 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6941 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6942 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6943 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6946 /* FIXME: Retrieve command line by walking the PEB of the process. */
6949 CloseHandle (h_proc
);
6955 /* Wrappers for winsock functions to map between our file descriptors
6956 and winsock's handles; also set h_errno for convenience.
6958 To allow Emacs to run on systems which don't have winsock support
6959 installed, we dynamically link to winsock on startup if present, and
6960 otherwise provide the minimum necessary functionality
6961 (eg. gethostname). */
6963 /* function pointers for relevant socket functions */
6964 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6965 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6966 int (PASCAL
*pfn_WSAGetLastError
) (void);
6967 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6968 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6969 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6970 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6971 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6972 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6973 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6974 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6975 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6976 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6977 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6978 int (PASCAL
*pfn_WSACleanup
) (void);
6980 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6981 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6982 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6983 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6984 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6985 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6986 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6987 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6988 const char * optval
, int optlen
);
6989 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6990 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6992 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6993 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6994 struct sockaddr
* from
, int * fromlen
);
6995 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6996 const struct sockaddr
* to
, int tolen
);
6998 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6999 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7000 #ifndef HANDLE_FLAG_INHERIT
7001 #define HANDLE_FLAG_INHERIT 1
7005 static int winsock_inuse
;
7010 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7012 release_listen_threads ();
7013 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7014 after WSAStartup returns successfully, but it seems reasonable
7015 to allow unloading winsock anyway in that case. */
7016 if (pfn_WSACleanup () == 0 ||
7017 pfn_WSAGetLastError () == WSAENETDOWN
)
7019 if (FreeLibrary (winsock_lib
))
7028 init_winsock (int load_now
)
7030 WSADATA winsockData
;
7032 if (winsock_lib
!= NULL
)
7035 pfn_SetHandleInformation
7036 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7037 "SetHandleInformation");
7039 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7041 if (winsock_lib
!= NULL
)
7043 /* dynamically link to socket functions */
7045 #define LOAD_PROC(fn) \
7046 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7049 LOAD_PROC (WSAStartup
);
7050 LOAD_PROC (WSASetLastError
);
7051 LOAD_PROC (WSAGetLastError
);
7052 LOAD_PROC (WSAEventSelect
);
7053 LOAD_PROC (WSACreateEvent
);
7054 LOAD_PROC (WSACloseEvent
);
7057 LOAD_PROC (connect
);
7058 LOAD_PROC (ioctlsocket
);
7061 LOAD_PROC (closesocket
);
7062 LOAD_PROC (shutdown
);
7065 LOAD_PROC (inet_addr
);
7066 LOAD_PROC (gethostname
);
7067 LOAD_PROC (gethostbyname
);
7068 LOAD_PROC (getservbyname
);
7069 LOAD_PROC (getpeername
);
7070 LOAD_PROC (WSACleanup
);
7071 LOAD_PROC (setsockopt
);
7073 LOAD_PROC (getsockname
);
7075 LOAD_PROC (recvfrom
);
7079 /* specify version 1.1 of winsock */
7080 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7082 if (winsockData
.wVersion
!= 0x101)
7087 /* Report that winsock exists and is usable, but leave
7088 socket functions disabled. I am assuming that calling
7089 WSAStartup does not require any network interaction,
7090 and in particular does not cause or require a dial-up
7091 connection to be established. */
7094 FreeLibrary (winsock_lib
);
7102 FreeLibrary (winsock_lib
);
7112 /* Function to map winsock error codes to errno codes for those errno
7113 code defined in errno.h (errno values not defined by errno.h are
7114 already in nt/inc/sys/socket.h). */
7121 if (winsock_lib
== NULL
)
7124 wsa_err
= pfn_WSAGetLastError ();
7128 case WSAEACCES
: errno
= EACCES
; break;
7129 case WSAEBADF
: errno
= EBADF
; break;
7130 case WSAEFAULT
: errno
= EFAULT
; break;
7131 case WSAEINTR
: errno
= EINTR
; break;
7132 case WSAEINVAL
: errno
= EINVAL
; break;
7133 case WSAEMFILE
: errno
= EMFILE
; break;
7134 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7135 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7136 default: errno
= wsa_err
; break;
7144 if (winsock_lib
!= NULL
)
7145 pfn_WSASetLastError (0);
7148 /* Extend strerror to handle the winsock-specific error codes. */
7152 } _wsa_errlist
[] = {
7153 {WSAEINTR
, "Interrupted function call"},
7154 {WSAEBADF
, "Bad file descriptor"},
7155 {WSAEACCES
, "Permission denied"},
7156 {WSAEFAULT
, "Bad address"},
7157 {WSAEINVAL
, "Invalid argument"},
7158 {WSAEMFILE
, "Too many open files"},
7160 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7161 {WSAEINPROGRESS
, "Operation now in progress"},
7162 {WSAEALREADY
, "Operation already in progress"},
7163 {WSAENOTSOCK
, "Socket operation on non-socket"},
7164 {WSAEDESTADDRREQ
, "Destination address required"},
7165 {WSAEMSGSIZE
, "Message too long"},
7166 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7167 {WSAENOPROTOOPT
, "Bad protocol option"},
7168 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7169 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7170 {WSAEOPNOTSUPP
, "Operation not supported"},
7171 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7172 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7173 {WSAEADDRINUSE
, "Address already in use"},
7174 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7175 {WSAENETDOWN
, "Network is down"},
7176 {WSAENETUNREACH
, "Network is unreachable"},
7177 {WSAENETRESET
, "Network dropped connection on reset"},
7178 {WSAECONNABORTED
, "Software caused connection abort"},
7179 {WSAECONNRESET
, "Connection reset by peer"},
7180 {WSAENOBUFS
, "No buffer space available"},
7181 {WSAEISCONN
, "Socket is already connected"},
7182 {WSAENOTCONN
, "Socket is not connected"},
7183 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7184 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7185 {WSAETIMEDOUT
, "Connection timed out"},
7186 {WSAECONNREFUSED
, "Connection refused"},
7187 {WSAELOOP
, "Network loop"}, /* not sure */
7188 {WSAENAMETOOLONG
, "Name is too long"},
7189 {WSAEHOSTDOWN
, "Host is down"},
7190 {WSAEHOSTUNREACH
, "No route to host"},
7191 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7192 {WSAEPROCLIM
, "Too many processes"},
7193 {WSAEUSERS
, "Too many users"}, /* not sure */
7194 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7195 {WSAESTALE
, "Data is stale"}, /* not sure */
7196 {WSAEREMOTE
, "Remote error"}, /* not sure */
7198 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7199 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7200 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7201 {WSAEDISCON
, "Graceful shutdown in progress"},
7203 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7204 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7205 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7206 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7207 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7208 {WSASYSCALLFAILURE
, "System call failure"},
7209 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7210 {WSATYPE_NOT_FOUND
, "Class type not found"},
7211 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7212 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7213 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7216 {WSAHOST_NOT_FOUND
, "Host not found"},
7217 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7218 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7219 {WSANO_DATA
, "Valid name, no data record of requested type"},
7225 sys_strerror (int error_no
)
7228 static char unknown_msg
[40];
7230 if (error_no
>= 0 && error_no
< sys_nerr
)
7231 return sys_errlist
[error_no
];
7233 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7234 if (_wsa_errlist
[i
].errnum
== error_no
)
7235 return _wsa_errlist
[i
].msg
;
7237 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7241 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7242 but I believe the method of keeping the socket handle separate (and
7243 insuring it is not inheritable) is the correct one. */
7245 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7247 static int socket_to_fd (SOCKET s
);
7250 sys_socket (int af
, int type
, int protocol
)
7254 if (winsock_lib
== NULL
)
7257 return INVALID_SOCKET
;
7262 /* call the real socket function */
7263 s
= pfn_socket (af
, type
, protocol
);
7265 if (s
!= INVALID_SOCKET
)
7266 return socket_to_fd (s
);
7272 /* Convert a SOCKET to a file descriptor. */
7274 socket_to_fd (SOCKET s
)
7279 /* Although under NT 3.5 _open_osfhandle will accept a socket
7280 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7281 that does not work under NT 3.1. However, we can get the same
7282 effect by using a backdoor function to replace an existing
7283 descriptor handle with the one we want. */
7285 /* allocate a file descriptor (with appropriate flags) */
7286 fd
= _open ("NUL:", _O_RDWR
);
7289 /* Make a non-inheritable copy of the socket handle. Note
7290 that it is possible that sockets aren't actually kernel
7291 handles, which appears to be the case on Windows 9x when
7292 the MS Proxy winsock client is installed. */
7294 /* Apparently there is a bug in NT 3.51 with some service
7295 packs, which prevents using DuplicateHandle to make a
7296 socket handle non-inheritable (causes WSACleanup to
7297 hang). The work-around is to use SetHandleInformation
7298 instead if it is available and implemented. */
7299 if (pfn_SetHandleInformation
)
7301 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7305 HANDLE parent
= GetCurrentProcess ();
7306 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7308 if (DuplicateHandle (parent
,
7314 DUPLICATE_SAME_ACCESS
))
7316 /* It is possible that DuplicateHandle succeeds even
7317 though the socket wasn't really a kernel handle,
7318 because a real handle has the same value. So
7319 test whether the new handle really is a socket. */
7320 long nonblocking
= 0;
7321 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7323 pfn_closesocket (s
);
7328 CloseHandle (new_s
);
7333 eassert (fd
< MAXDESC
);
7334 fd_info
[fd
].hnd
= (HANDLE
) s
;
7336 /* set our own internal flags */
7337 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7343 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7345 /* attach child_process to fd_info */
7346 if (fd_info
[ fd
].cp
!= NULL
)
7348 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7352 fd_info
[ fd
].cp
= cp
;
7355 winsock_inuse
++; /* count open sockets */
7363 pfn_closesocket (s
);
7369 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7371 if (winsock_lib
== NULL
)
7374 return SOCKET_ERROR
;
7378 if (fd_info
[s
].flags
& FILE_SOCKET
)
7380 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7381 if (rc
== SOCKET_ERROR
)
7386 return SOCKET_ERROR
;
7390 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7392 if (winsock_lib
== NULL
)
7395 return SOCKET_ERROR
;
7399 if (fd_info
[s
].flags
& FILE_SOCKET
)
7401 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7402 if (rc
== SOCKET_ERROR
)
7407 return SOCKET_ERROR
;
7411 sys_htons (u_short hostshort
)
7413 return (winsock_lib
!= NULL
) ?
7414 pfn_htons (hostshort
) : hostshort
;
7418 sys_ntohs (u_short netshort
)
7420 return (winsock_lib
!= NULL
) ?
7421 pfn_ntohs (netshort
) : netshort
;
7425 sys_inet_addr (const char * cp
)
7427 return (winsock_lib
!= NULL
) ?
7428 pfn_inet_addr (cp
) : INADDR_NONE
;
7432 sys_gethostname (char * name
, int namelen
)
7434 if (winsock_lib
!= NULL
)
7439 retval
= pfn_gethostname (name
, namelen
);
7440 if (retval
== SOCKET_ERROR
)
7445 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7446 return !GetComputerName (name
, (DWORD
*)&namelen
);
7449 return SOCKET_ERROR
;
7453 sys_gethostbyname (const char * name
)
7455 struct hostent
* host
;
7456 int h_err
= h_errno
;
7458 if (winsock_lib
== NULL
)
7460 h_errno
= NO_RECOVERY
;
7466 host
= pfn_gethostbyname (name
);
7478 sys_getservbyname (const char * name
, const char * proto
)
7480 struct servent
* serv
;
7482 if (winsock_lib
== NULL
)
7489 serv
= pfn_getservbyname (name
, proto
);
7496 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7498 if (winsock_lib
== NULL
)
7501 return SOCKET_ERROR
;
7505 if (fd_info
[s
].flags
& FILE_SOCKET
)
7507 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7508 if (rc
== SOCKET_ERROR
)
7513 return SOCKET_ERROR
;
7517 sys_shutdown (int s
, int how
)
7519 if (winsock_lib
== NULL
)
7522 return SOCKET_ERROR
;
7526 if (fd_info
[s
].flags
& FILE_SOCKET
)
7528 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7529 if (rc
== SOCKET_ERROR
)
7534 return SOCKET_ERROR
;
7538 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7540 if (winsock_lib
== NULL
)
7543 return SOCKET_ERROR
;
7547 if (fd_info
[s
].flags
& FILE_SOCKET
)
7549 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7550 (const char *)optval
, optlen
);
7551 if (rc
== SOCKET_ERROR
)
7556 return SOCKET_ERROR
;
7560 sys_listen (int s
, int backlog
)
7562 if (winsock_lib
== NULL
)
7565 return SOCKET_ERROR
;
7569 if (fd_info
[s
].flags
& FILE_SOCKET
)
7571 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7572 if (rc
== SOCKET_ERROR
)
7575 fd_info
[s
].flags
|= FILE_LISTEN
;
7579 return SOCKET_ERROR
;
7583 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7585 if (winsock_lib
== NULL
)
7588 return SOCKET_ERROR
;
7592 if (fd_info
[s
].flags
& FILE_SOCKET
)
7594 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7595 if (rc
== SOCKET_ERROR
)
7600 return SOCKET_ERROR
;
7604 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7606 if (winsock_lib
== NULL
)
7613 if (fd_info
[s
].flags
& FILE_LISTEN
)
7615 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7617 if (t
== INVALID_SOCKET
)
7620 fd
= socket_to_fd (t
);
7624 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7625 ResetEvent (fd_info
[s
].cp
->char_avail
);
7634 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7635 struct sockaddr
* from
, int * fromlen
)
7637 if (winsock_lib
== NULL
)
7640 return SOCKET_ERROR
;
7644 if (fd_info
[s
].flags
& FILE_SOCKET
)
7646 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7647 if (rc
== SOCKET_ERROR
)
7652 return SOCKET_ERROR
;
7656 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7657 const struct sockaddr
* to
, int tolen
)
7659 if (winsock_lib
== NULL
)
7662 return SOCKET_ERROR
;
7666 if (fd_info
[s
].flags
& FILE_SOCKET
)
7668 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7669 if (rc
== SOCKET_ERROR
)
7674 return SOCKET_ERROR
;
7677 /* Windows does not have an fcntl function. Provide an implementation
7678 good enough for Emacs. */
7680 fcntl (int s
, int cmd
, int options
)
7682 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7683 invoked in a context where fd1 is closed and all descriptors less
7684 than fd1 are open, so sys_dup is an adequate implementation. */
7685 if (cmd
== F_DUPFD_CLOEXEC
)
7688 if (winsock_lib
== NULL
)
7695 if (fd_info
[s
].flags
& FILE_SOCKET
)
7697 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7699 unsigned long nblock
= 1;
7700 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7701 if (rc
== SOCKET_ERROR
)
7703 /* Keep track of the fact that we set this to non-blocking. */
7704 fd_info
[s
].flags
|= FILE_NDELAY
;
7710 return SOCKET_ERROR
;
7714 return SOCKET_ERROR
;
7718 /* Shadow main io functions: we need to handle pipes and sockets more
7719 intelligently, and implement non-blocking mode as well. */
7732 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7734 child_process
* cp
= fd_info
[fd
].cp
;
7736 fd_info
[fd
].cp
= NULL
;
7738 if (CHILD_ACTIVE (cp
))
7740 /* if last descriptor to active child_process then cleanup */
7742 for (i
= 0; i
< MAXDESC
; i
++)
7746 if (fd_info
[i
].cp
== cp
)
7751 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7753 if (winsock_lib
== NULL
) emacs_abort ();
7755 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7756 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7758 winsock_inuse
--; /* count open sockets */
7760 /* If the process handle is NULL, it's either a socket
7761 or serial connection, or a subprocess that was
7762 already reaped by reap_subprocess, but whose
7763 resources were not yet freed, because its output was
7764 not fully read yet by the time it was reaped. (This
7765 usually happens with async subprocesses whose output
7766 is being read by Emacs.) Otherwise, this process was
7767 not reaped yet, so we set its FD to a negative value
7768 to make sure sys_select will eventually get to
7769 calling the SIGCHLD handler for it, which will then
7770 invoke waitpid and reap_subprocess. */
7771 if (cp
->procinfo
.hProcess
== NULL
)
7779 if (fd
>= 0 && fd
< MAXDESC
)
7780 fd_info
[fd
].flags
= 0;
7782 /* Note that sockets do not need special treatment here (at least on
7783 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7784 closesocket is equivalent to CloseHandle, which is to be expected
7785 because socket handles are fully fledged kernel handles. */
7797 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7799 /* duplicate our internal info as well */
7800 fd_info
[new_fd
] = fd_info
[fd
];
7806 sys_dup2 (int src
, int dst
)
7810 if (dst
< 0 || dst
>= MAXDESC
)
7816 /* make sure we close the destination first if it's a pipe or socket */
7817 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7820 rc
= _dup2 (src
, dst
);
7823 /* duplicate our internal info as well */
7824 fd_info
[dst
] = fd_info
[src
];
7830 pipe2 (int * phandles
, int pipe2_flags
)
7835 eassert (pipe2_flags
== O_CLOEXEC
);
7837 /* make pipe handles non-inheritable; when we spawn a child, we
7838 replace the relevant handle with an inheritable one. Also put
7839 pipes into binary mode; we will do text mode translation ourselves
7841 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7845 /* Protect against overflow, since Windows can open more handles than
7846 our fd_info array has room for. */
7847 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7849 _close (phandles
[0]);
7850 _close (phandles
[1]);
7856 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7857 fd_info
[phandles
[0]].flags
= flags
;
7859 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7860 fd_info
[phandles
[1]].flags
= flags
;
7867 /* Function to do blocking read of one byte, needed to implement
7868 select. It is only allowed on communication ports, sockets, or
7871 _sys_read_ahead (int fd
)
7876 if (fd
< 0 || fd
>= MAXDESC
)
7877 return STATUS_READ_ERROR
;
7879 cp
= fd_info
[fd
].cp
;
7881 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7882 return STATUS_READ_ERROR
;
7884 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7885 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7887 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7891 cp
->status
= STATUS_READ_IN_PROGRESS
;
7893 if (fd_info
[fd
].flags
& FILE_PIPE
)
7895 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7897 /* Give subprocess time to buffer some more output for us before
7898 reporting that input is available; we need this because Windows 95
7899 connects DOS programs to pipes by making the pipe appear to be
7900 the normal console stdout - as a result most DOS programs will
7901 write to stdout without buffering, ie. one character at a
7902 time. Even some W32 programs do this - "dir" in a command
7903 shell on NT is very slow if we don't do this. */
7906 int wait
= w32_pipe_read_delay
;
7912 /* Yield remainder of our time slice, effectively giving a
7913 temporary priority boost to the child process. */
7917 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7919 HANDLE hnd
= fd_info
[fd
].hnd
;
7920 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7923 /* Configure timeouts for blocking read. */
7924 if (!GetCommTimeouts (hnd
, &ct
))
7926 cp
->status
= STATUS_READ_ERROR
;
7927 return STATUS_READ_ERROR
;
7929 ct
.ReadIntervalTimeout
= 0;
7930 ct
.ReadTotalTimeoutMultiplier
= 0;
7931 ct
.ReadTotalTimeoutConstant
= 0;
7932 if (!SetCommTimeouts (hnd
, &ct
))
7934 cp
->status
= STATUS_READ_ERROR
;
7935 return STATUS_READ_ERROR
;
7938 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7940 if (GetLastError () != ERROR_IO_PENDING
)
7942 cp
->status
= STATUS_READ_ERROR
;
7943 return STATUS_READ_ERROR
;
7945 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7947 cp
->status
= STATUS_READ_ERROR
;
7948 return STATUS_READ_ERROR
;
7952 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7954 unsigned long nblock
= 0;
7955 /* We always want this to block, so temporarily disable NDELAY. */
7956 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7957 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7959 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7961 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7964 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7968 if (rc
== sizeof (char))
7969 cp
->status
= STATUS_READ_SUCCEEDED
;
7971 cp
->status
= STATUS_READ_FAILED
;
7977 _sys_wait_accept (int fd
)
7983 if (fd
< 0 || fd
>= MAXDESC
)
7984 return STATUS_READ_ERROR
;
7986 cp
= fd_info
[fd
].cp
;
7988 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7989 return STATUS_READ_ERROR
;
7991 cp
->status
= STATUS_READ_FAILED
;
7993 hEv
= pfn_WSACreateEvent ();
7994 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7995 if (rc
!= SOCKET_ERROR
)
7998 rc
= WaitForSingleObject (hEv
, 500);
8000 } while (rc
== WAIT_TIMEOUT
8001 && cp
->status
!= STATUS_READ_ERROR
8003 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8004 if (rc
== WAIT_OBJECT_0
)
8005 cp
->status
= STATUS_READ_SUCCEEDED
;
8007 pfn_WSACloseEvent (hEv
);
8013 sys_read (int fd
, char * buffer
, unsigned int count
)
8018 char * orig_buffer
= buffer
;
8026 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8028 child_process
*cp
= fd_info
[fd
].cp
;
8030 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8038 /* re-read CR carried over from last read */
8039 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8041 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8045 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8048 /* presence of a child_process structure means we are operating in
8049 non-blocking mode - otherwise we just call _read directly.
8050 Note that the child_process structure might be missing because
8051 reap_subprocess has been called; in this case the pipe is
8052 already broken, so calling _read on it is okay. */
8055 int current_status
= cp
->status
;
8057 switch (current_status
)
8059 case STATUS_READ_FAILED
:
8060 case STATUS_READ_ERROR
:
8061 /* report normal EOF if nothing in buffer */
8063 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8066 case STATUS_READ_READY
:
8067 case STATUS_READ_IN_PROGRESS
:
8068 DebPrint (("sys_read called when read is in progress\n"));
8069 errno
= EWOULDBLOCK
;
8072 case STATUS_READ_SUCCEEDED
:
8073 /* consume read-ahead char */
8074 *buffer
++ = cp
->chr
;
8077 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8078 ResetEvent (cp
->char_avail
);
8080 case STATUS_READ_ACKNOWLEDGED
:
8084 DebPrint (("sys_read: bad status %d\n", current_status
));
8089 if (fd_info
[fd
].flags
& FILE_PIPE
)
8091 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8092 to_read
= min (waiting
, (DWORD
) count
);
8095 nchars
+= _read (fd
, buffer
, to_read
);
8097 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8099 HANDLE hnd
= fd_info
[fd
].hnd
;
8100 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8106 /* Configure timeouts for non-blocking read. */
8107 if (!GetCommTimeouts (hnd
, &ct
))
8112 ct
.ReadIntervalTimeout
= MAXDWORD
;
8113 ct
.ReadTotalTimeoutMultiplier
= 0;
8114 ct
.ReadTotalTimeoutConstant
= 0;
8115 if (!SetCommTimeouts (hnd
, &ct
))
8121 if (!ResetEvent (ovl
->hEvent
))
8126 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8128 if (GetLastError () != ERROR_IO_PENDING
)
8133 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8142 else /* FILE_SOCKET */
8144 if (winsock_lib
== NULL
) emacs_abort ();
8146 /* do the equivalent of a non-blocking read */
8147 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8148 if (waiting
== 0 && nchars
== 0)
8150 errno
= EWOULDBLOCK
;
8156 /* always use binary mode for sockets */
8157 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8158 if (res
== SOCKET_ERROR
)
8160 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8161 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8171 int nread
= _read (fd
, buffer
, count
);
8174 else if (nchars
== 0)
8179 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8180 /* Perform text mode translation if required. */
8181 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8183 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8184 /* If buffer contains only CR, return that. To be absolutely
8185 sure we should attempt to read the next char, but in
8186 practice a CR to be followed by LF would not appear by
8187 itself in the buffer. */
8188 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8190 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8196 nchars
= _read (fd
, buffer
, count
);
8201 /* From w32xfns.c */
8202 extern HANDLE interrupt_handle
;
8204 /* For now, don't bother with a non-blocking mode */
8206 sys_write (int fd
, const void * buffer
, unsigned int count
)
8216 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8218 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8224 /* Perform text mode translation if required. */
8225 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8227 char * tmpbuf
= alloca (count
* 2);
8228 unsigned char * src
= (void *)buffer
;
8229 unsigned char * dst
= tmpbuf
;
8234 unsigned char *next
;
8235 /* copy next line or remaining bytes */
8236 next
= _memccpy (dst
, src
, '\n', nbytes
);
8239 /* copied one line ending with '\n' */
8240 int copied
= next
- dst
;
8243 /* insert '\r' before '\n' */
8250 /* copied remaining partial line -> now finished */
8257 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8259 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8260 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8261 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8264 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8266 if (GetLastError () != ERROR_IO_PENDING
)
8271 if (detect_input_pending ())
8272 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8275 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8276 if (active
== WAIT_OBJECT_0
)
8277 { /* User pressed C-g, cancel write, then leave. Don't bother
8278 cleaning up as we may only get stuck in buggy drivers. */
8279 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8284 if (active
== WAIT_OBJECT_0
+ 1
8285 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8292 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8294 unsigned long nblock
= 0;
8295 if (winsock_lib
== NULL
) emacs_abort ();
8297 /* TODO: implement select() properly so non-blocking I/O works. */
8298 /* For now, make sure the write blocks. */
8299 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8300 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8302 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8304 /* Set the socket back to non-blocking if it was before,
8305 for other operations that support it. */
8306 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8309 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8312 if (nchars
== SOCKET_ERROR
)
8314 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8315 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8321 /* Some networked filesystems don't like too large writes, so
8322 break them into smaller chunks. See the Comments section of
8323 the MSDN documentation of WriteFile for details behind the
8324 choice of the value of CHUNK below. See also the thread
8325 http://thread.gmane.org/gmane.comp.version-control.git/145294
8326 in the git mailing list. */
8327 const unsigned char *p
= buffer
;
8328 const unsigned chunk
= 30 * 1024 * 1024;
8333 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8334 int n
= _write (fd
, p
, this_chunk
);
8342 else if (n
< this_chunk
)
8353 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8355 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8357 /* Return information about network interface IFNAME, or about all
8358 interfaces (if IFNAME is nil). */
8360 network_interface_get_info (Lisp_Object ifname
)
8362 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8363 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8364 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8365 Lisp_Object res
= Qnil
;
8367 if (retval
== ERROR_BUFFER_OVERFLOW
)
8369 ainfo
= xrealloc (ainfo
, ainfo_len
);
8370 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8373 if (retval
== ERROR_SUCCESS
)
8375 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8376 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8378 struct sockaddr_in sa
;
8380 /* For the below, we need some winsock functions, so make sure
8381 the winsock DLL is loaded. If we cannot successfully load
8382 it, they will have no use of the information we provide,
8384 if (!winsock_lib
&& !init_winsock (1))
8387 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8389 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8391 /* Present Unix-compatible interface names, instead of the
8392 Windows names, which are really GUIDs not readable by
8394 static const char *ifmt
[] = {
8395 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8410 switch (adapter
->Type
)
8412 case MIB_IF_TYPE_ETHERNET
:
8413 /* Windows before Vista reports wireless adapters as
8414 Ethernet. Work around by looking at the Description
8416 if (strstr (adapter
->Description
, "Wireless "))
8419 if_num
= wlan_count
++;
8423 ifmt_idx
= ETHERNET
;
8424 if_num
= eth_count
++;
8427 case MIB_IF_TYPE_TOKENRING
:
8428 ifmt_idx
= TOKENRING
;
8429 if_num
= tr_count
++;
8431 case MIB_IF_TYPE_FDDI
:
8433 if_num
= fddi_count
++;
8435 case MIB_IF_TYPE_PPP
:
8437 if_num
= ppp_count
++;
8439 case MIB_IF_TYPE_SLIP
:
8441 if_num
= sl_count
++;
8443 case IF_TYPE_IEEE80211
:
8445 if_num
= wlan_count
++;
8447 case MIB_IF_TYPE_LOOPBACK
:
8450 ifmt_idx
= LOOPBACK
;
8451 if_num
= lo_count
++;
8457 ifmt_idx
= OTHER_IF
;
8458 if_num
= ifx_count
++;
8461 if (ifmt_idx
== NONE
)
8463 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8465 sa
.sin_family
= AF_INET
;
8466 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8467 if (ip_addr
== INADDR_NONE
)
8469 /* Bogus address, skip this interface. */
8472 sa
.sin_addr
.s_addr
= ip_addr
;
8475 res
= Fcons (Fcons (build_string (namebuf
),
8476 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8477 sizeof (struct sockaddr
))),
8479 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8481 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8482 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8483 Lisp_Object flags
= Qnil
;
8487 /* Flags. We guess most of them by type, since the
8488 Windows flags are different and hard to get by. */
8489 flags
= Fcons (intern ("up"), flags
);
8490 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8492 flags
= Fcons (intern ("broadcast"), flags
);
8493 flags
= Fcons (intern ("multicast"), flags
);
8495 flags
= Fcons (intern ("running"), flags
);
8496 if (ifmt_idx
== PPP
)
8498 flags
= Fcons (intern ("pointopoint"), flags
);
8499 flags
= Fcons (intern ("noarp"), flags
);
8501 if (adapter
->HaveWins
)
8502 flags
= Fcons (intern ("WINS"), flags
);
8503 if (adapter
->DhcpEnabled
)
8504 flags
= Fcons (intern ("dynamic"), flags
);
8506 res
= Fcons (flags
, res
);
8508 /* Hardware address and its family. */
8509 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8510 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8511 /* Windows does not support AF_LINK or AF_PACKET family
8512 of addresses. Use an arbitrary family number that is
8513 identical to what GNU/Linux returns. */
8514 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8517 sa
.sin_family
= AF_INET
;
8518 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8519 if (net_mask
!= INADDR_NONE
)
8521 sa
.sin_addr
.s_addr
= net_mask
;
8523 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8524 sizeof (struct sockaddr
)),
8528 res
= Fcons (Qnil
, res
);
8530 sa
.sin_family
= AF_INET
;
8531 if (ip_addr
!= INADDR_NONE
)
8533 /* Broadcast address is only reported by
8534 GetAdaptersAddresses, which is of limited
8535 availability. Generate it on our own. */
8536 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8538 sa
.sin_addr
.s_addr
= bcast_addr
;
8540 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8541 sizeof (struct sockaddr
)),
8545 sa
.sin_addr
.s_addr
= ip_addr
;
8547 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8548 sizeof (struct sockaddr
)),
8552 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8555 /* GetAdaptersInfo is documented to not report loopback
8556 interfaces, so we generate one out of thin air. */
8559 sa
.sin_family
= AF_INET
;
8563 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8564 res
= Fcons (Fcons (build_string ("lo"),
8565 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8566 sizeof (struct sockaddr
))),
8569 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8571 res
= Fcons (Fcons (intern ("running"),
8572 Fcons (intern ("loopback"),
8573 Fcons (intern ("up"), Qnil
))), Qnil
);
8574 /* 772 is what 3 different GNU/Linux systems report for
8575 the loopback interface. */
8576 res
= Fcons (Fcons (make_number (772),
8577 Fmake_vector (make_number (6),
8580 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8581 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8582 sizeof (struct sockaddr
)),
8584 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8585 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8586 sizeof (struct sockaddr
)),
8588 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8589 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8590 sizeof (struct sockaddr
)),
8603 network_interface_list (void)
8605 return network_interface_get_info (Qnil
);
8609 network_interface_info (Lisp_Object ifname
)
8611 return network_interface_get_info (ifname
);
8615 /* The Windows CRT functions are "optimized for speed", so they don't
8616 check for timezone and DST changes if they were last called less
8617 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8618 all Emacs features that repeatedly call time functions (e.g.,
8619 display-time) are in real danger of missing timezone and DST
8620 changes. Calling tzset before each localtime call fixes that. */
8622 sys_localtime (const time_t *t
)
8625 return localtime (t
);
8630 /* Try loading LIBRARY_ID from the file(s) specified in
8631 Vdynamic_library_alist. If the library is loaded successfully,
8632 return the handle of the DLL, and record the filename in the
8633 property :loaded-from of LIBRARY_ID. If the library could not be
8634 found, or when it was already loaded (because the handle is not
8635 recorded anywhere, and so is lost after use), return NULL.
8637 We could also save the handle in :loaded-from, but currently
8638 there's no use case for it. */
8640 w32_delayed_load (Lisp_Object library_id
)
8642 HMODULE dll_handle
= NULL
;
8644 CHECK_SYMBOL (library_id
);
8646 if (CONSP (Vdynamic_library_alist
)
8647 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8649 Lisp_Object found
= Qnil
;
8650 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8653 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8655 Lisp_Object dll
= XCAR (dlls
);
8656 char name
[MAX_UTF8_PATH
];
8660 dll
= ENCODE_FILE (dll
);
8661 if (w32_unicode_filenames
)
8663 wchar_t name_w
[MAX_PATH
];
8665 filename_to_utf16 (SSDATA (dll
), name_w
);
8666 dll_handle
= LoadLibraryW (name_w
);
8669 res
= GetModuleFileNameW (dll_handle
, name_w
,
8672 filename_from_utf16 (name_w
, name
);
8677 char name_a
[MAX_PATH
];
8679 filename_to_ansi (SSDATA (dll
), name_a
);
8680 dll_handle
= LoadLibraryA (name_a
);
8683 res
= GetModuleFileNameA (dll_handle
, name_a
,
8686 filename_from_ansi (name_a
, name
);
8691 ptrdiff_t len
= strlen (name
);
8694 /* Possibly truncated */
8695 ? make_specified_string (name
, -1, len
, 1)
8701 Fput (library_id
, QCloaded_from
, found
);
8709 check_windows_init_file (void)
8711 /* A common indication that Emacs is not installed properly is when
8712 it cannot find the Windows installation file. If this file does
8713 not exist in the expected place, tell the user. */
8715 if (!noninteractive
&& !inhibit_window_system
8716 /* Vload_path is not yet initialized when we are loading
8718 && NILP (Vpurify_flag
))
8720 Lisp_Object init_file
;
8723 /* Implementation note: this function runs early during Emacs
8724 startup, before startup.el is run. So Vload_path is still in
8725 its initial unibyte form, but it holds UTF-8 encoded file
8726 names, since init_callproc was already called. So we do not
8727 need to ENCODE_FILE here, but we do need to convert the file
8728 names from UTF-8 to ANSI. */
8729 init_file
= build_string ("term/w32-win");
8730 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
8733 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8734 char *init_file_name
= SDATA (init_file
);
8735 char *load_path
= SDATA (load_path_print
);
8736 char *buffer
= alloca (1024
8737 + strlen (init_file_name
)
8738 + strlen (load_path
));
8743 "The Emacs Windows initialization file \"%s.el\" "
8744 "could not be found in your Emacs installation. "
8745 "Emacs checked the following directories for this file:\n"
8747 "When Emacs cannot find this file, it usually means that it "
8748 "was not installed properly, or its distribution file was "
8749 "not unpacked properly.\nSee the README.W32 file in the "
8750 "top-level Emacs directory for more information.",
8751 init_file_name
, load_path
);
8752 needed
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8756 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8758 MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8760 needed
= WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8761 NULL
, 0, NULL
, NULL
);
8764 char *msg_a
= alloca (needed
+ 1);
8766 WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8773 "Emacs Abort Dialog",
8774 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8775 /* Use the low-level system abort. */
8786 term_ntproc (int ignored
)
8792 /* shutdown the socket interface if necessary */
8799 init_ntproc (int dumping
)
8801 sigset_t initial_mask
= 0;
8803 /* Initialize the socket interface now if available and requested by
8804 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8805 delayed until open-network-stream is called (w32-has-winsock can
8806 also be used to dynamically load or reload winsock).
8808 Conveniently, init_environment is called before us, so
8809 PRELOAD_WINSOCK can be set in the registry. */
8811 /* Always initialize this correctly. */
8814 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8815 init_winsock (TRUE
);
8817 /* Initial preparation for subprocess support: replace our standard
8818 handles with non-inheritable versions. */
8821 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8822 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8823 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8825 parent
= GetCurrentProcess ();
8827 /* ignore errors when duplicating and closing; typically the
8828 handles will be invalid when running as a gui program. */
8829 DuplicateHandle (parent
,
8830 GetStdHandle (STD_INPUT_HANDLE
),
8835 DUPLICATE_SAME_ACCESS
);
8837 DuplicateHandle (parent
,
8838 GetStdHandle (STD_OUTPUT_HANDLE
),
8843 DUPLICATE_SAME_ACCESS
);
8845 DuplicateHandle (parent
,
8846 GetStdHandle (STD_ERROR_HANDLE
),
8851 DUPLICATE_SAME_ACCESS
);
8857 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8858 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8860 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8863 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8864 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8866 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8869 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8870 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8872 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8876 /* unfortunately, atexit depends on implementation of malloc */
8877 /* atexit (term_ntproc); */
8880 /* Make sure we start with all signals unblocked. */
8881 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8882 signal (SIGABRT
, term_ntproc
);
8886 /* determine which drives are fixed, for GetCachedVolumeInformation */
8888 /* GetDriveType must have trailing backslash. */
8889 char drive
[] = "A:\\";
8891 /* Loop over all possible drive letters */
8892 while (*drive
<= 'Z')
8894 /* Record if this drive letter refers to a fixed drive. */
8895 fixed_drives
[DRIVE_INDEX (*drive
)] =
8896 (GetDriveType (drive
) == DRIVE_FIXED
);
8901 /* Reset the volume info cache. */
8902 volume_cache
= NULL
;
8907 shutdown_handler ensures that buffers' autosave files are
8908 up to date when the user logs off, or the system shuts down.
8911 shutdown_handler (DWORD type
)
8913 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8914 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8915 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8916 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8918 /* Shut down cleanly, making sure autosave files are up to date. */
8919 shut_down_emacs (0, Qnil
);
8922 /* Allow other handlers to handle this signal. */
8926 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
8927 NT, return a handle to GDI32.DLL. */
8929 maybe_load_unicows_dll (void)
8931 if (os_subtype
== OS_9X
)
8933 HANDLE ret
= LoadLibrary ("Unicows.dll");
8940 button
= MessageBox (NULL
,
8941 "Emacs cannot load the UNICOWS.DLL library.\n"
8942 "This library is essential for using Emacs\n"
8943 "on this system. You need to install it.\n\n"
8944 "Emacs will exit when you click OK.",
8945 "Emacs cannot load UNICOWS.DLL",
8946 MB_ICONERROR
| MB_TASKMODAL
8947 | MB_SETFOREGROUND
| MB_OK
);
8957 return LoadLibrary ("Gdi32.dll");
8961 globals_of_w32 is used to initialize those global variables that
8962 must always be initialized on startup even when the global variable
8963 initialized is non zero (see the function main in emacs.c).
8966 globals_of_w32 (void)
8968 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8970 get_process_times_fn
= (GetProcessTimes_Proc
)
8971 GetProcAddress (kernel32
, "GetProcessTimes");
8973 DEFSYM (QCloaded_from
, ":loaded-from");
8975 g_b_init_is_windows_9x
= 0;
8976 g_b_init_open_process_token
= 0;
8977 g_b_init_get_token_information
= 0;
8978 g_b_init_lookup_account_sid
= 0;
8979 g_b_init_get_sid_sub_authority
= 0;
8980 g_b_init_get_sid_sub_authority_count
= 0;
8981 g_b_init_get_security_info
= 0;
8982 g_b_init_get_file_security_w
= 0;
8983 g_b_init_get_file_security_a
= 0;
8984 g_b_init_get_security_descriptor_owner
= 0;
8985 g_b_init_get_security_descriptor_group
= 0;
8986 g_b_init_is_valid_sid
= 0;
8987 g_b_init_create_toolhelp32_snapshot
= 0;
8988 g_b_init_process32_first
= 0;
8989 g_b_init_process32_next
= 0;
8990 g_b_init_open_thread_token
= 0;
8991 g_b_init_impersonate_self
= 0;
8992 g_b_init_revert_to_self
= 0;
8993 g_b_init_get_process_memory_info
= 0;
8994 g_b_init_get_process_working_set_size
= 0;
8995 g_b_init_global_memory_status
= 0;
8996 g_b_init_global_memory_status_ex
= 0;
8997 g_b_init_equal_sid
= 0;
8998 g_b_init_copy_sid
= 0;
8999 g_b_init_get_length_sid
= 0;
9000 g_b_init_get_native_system_info
= 0;
9001 g_b_init_get_system_times
= 0;
9002 g_b_init_create_symbolic_link_w
= 0;
9003 g_b_init_create_symbolic_link_a
= 0;
9004 g_b_init_get_security_descriptor_dacl
= 0;
9005 g_b_init_convert_sd_to_sddl
= 0;
9006 g_b_init_convert_sddl_to_sd
= 0;
9007 g_b_init_is_valid_security_descriptor
= 0;
9008 g_b_init_set_file_security_w
= 0;
9009 g_b_init_set_file_security_a
= 0;
9010 g_b_init_set_named_security_info_w
= 0;
9011 g_b_init_set_named_security_info_a
= 0;
9012 g_b_init_get_adapters_info
= 0;
9013 num_of_processors
= 0;
9014 /* The following sets a handler for shutdown notifications for
9015 console apps. This actually applies to Emacs in both console and
9016 GUI modes, since we had to fool windows into thinking emacs is a
9017 console application to get console mode to work. */
9018 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9020 /* "None" is the default group name on standalone workstations. */
9021 strcpy (dflt_group_name
, "None");
9023 /* Reset, in case it has some value inherited from dump time. */
9024 w32_stat_get_owner_group
= 0;
9026 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9027 (a.k.a. "wide") APIs to invoke functions that accept file
9029 if (is_windows_9x ())
9030 w32_unicode_filenames
= 0;
9032 w32_unicode_filenames
= 1;
9035 /* For make-serial-process */
9037 serial_open (Lisp_Object port_obj
)
9039 char *port
= SSDATA (port_obj
);
9044 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9045 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9046 if (hnd
== INVALID_HANDLE_VALUE
)
9047 error ("Could not open %s", port
);
9048 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9050 error ("Could not open %s", port
);
9054 error ("Could not create child process");
9056 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9057 fd_info
[ fd
].hnd
= hnd
;
9058 fd_info
[ fd
].flags
|=
9059 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9060 if (fd_info
[ fd
].cp
!= NULL
)
9062 error ("fd_info[fd = %d] is already in use", fd
);
9064 fd_info
[ fd
].cp
= cp
;
9065 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9066 if (cp
->ovl_read
.hEvent
== NULL
)
9067 error ("Could not create read event");
9068 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9069 if (cp
->ovl_write
.hEvent
== NULL
)
9070 error ("Could not create write event");
9075 /* For serial-process-configure */
9077 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9079 Lisp_Object childp2
= Qnil
;
9080 Lisp_Object tem
= Qnil
;
9084 char summary
[4] = "???"; /* This usually becomes "8N1". */
9086 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9087 error ("Not a serial process");
9088 hnd
= fd_info
[ p
->outfd
].hnd
;
9090 childp2
= Fcopy_sequence (p
->childp
);
9092 /* Initialize timeouts for blocking read and blocking write. */
9093 if (!GetCommTimeouts (hnd
, &ct
))
9094 error ("GetCommTimeouts() failed");
9095 ct
.ReadIntervalTimeout
= 0;
9096 ct
.ReadTotalTimeoutMultiplier
= 0;
9097 ct
.ReadTotalTimeoutConstant
= 0;
9098 ct
.WriteTotalTimeoutMultiplier
= 0;
9099 ct
.WriteTotalTimeoutConstant
= 0;
9100 if (!SetCommTimeouts (hnd
, &ct
))
9101 error ("SetCommTimeouts() failed");
9102 /* Read port attributes and prepare default configuration. */
9103 memset (&dcb
, 0, sizeof (dcb
));
9104 dcb
.DCBlength
= sizeof (DCB
);
9105 if (!GetCommState (hnd
, &dcb
))
9106 error ("GetCommState() failed");
9109 dcb
.fAbortOnError
= FALSE
;
9110 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9115 /* Configure speed. */
9116 if (!NILP (Fplist_member (contact
, QCspeed
)))
9117 tem
= Fplist_get (contact
, QCspeed
);
9119 tem
= Fplist_get (p
->childp
, QCspeed
);
9121 dcb
.BaudRate
= XINT (tem
);
9122 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9124 /* Configure bytesize. */
9125 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9126 tem
= Fplist_get (contact
, QCbytesize
);
9128 tem
= Fplist_get (p
->childp
, QCbytesize
);
9130 tem
= make_number (8);
9132 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9133 error (":bytesize must be nil (8), 7, or 8");
9134 dcb
.ByteSize
= XINT (tem
);
9135 summary
[0] = XINT (tem
) + '0';
9136 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9138 /* Configure parity. */
9139 if (!NILP (Fplist_member (contact
, QCparity
)))
9140 tem
= Fplist_get (contact
, QCparity
);
9142 tem
= Fplist_get (p
->childp
, QCparity
);
9143 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9144 error (":parity must be nil (no parity), `even', or `odd'");
9145 dcb
.fParity
= FALSE
;
9146 dcb
.Parity
= NOPARITY
;
9147 dcb
.fErrorChar
= FALSE
;
9152 else if (EQ (tem
, Qeven
))
9156 dcb
.Parity
= EVENPARITY
;
9157 dcb
.fErrorChar
= TRUE
;
9159 else if (EQ (tem
, Qodd
))
9163 dcb
.Parity
= ODDPARITY
;
9164 dcb
.fErrorChar
= TRUE
;
9166 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9168 /* Configure stopbits. */
9169 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9170 tem
= Fplist_get (contact
, QCstopbits
);
9172 tem
= Fplist_get (p
->childp
, QCstopbits
);
9174 tem
= make_number (1);
9176 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9177 error (":stopbits must be nil (1 stopbit), 1, or 2");
9178 summary
[2] = XINT (tem
) + '0';
9179 if (XINT (tem
) == 1)
9180 dcb
.StopBits
= ONESTOPBIT
;
9181 else if (XINT (tem
) == 2)
9182 dcb
.StopBits
= TWOSTOPBITS
;
9183 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9185 /* Configure flowcontrol. */
9186 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9187 tem
= Fplist_get (contact
, QCflowcontrol
);
9189 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9190 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9191 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9192 dcb
.fOutxCtsFlow
= FALSE
;
9193 dcb
.fOutxDsrFlow
= FALSE
;
9194 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9195 dcb
.fDsrSensitivity
= FALSE
;
9196 dcb
.fTXContinueOnXoff
= FALSE
;
9199 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9200 dcb
.XonChar
= 17; /* Control-Q */
9201 dcb
.XoffChar
= 19; /* Control-S */
9204 /* Already configured. */
9206 else if (EQ (tem
, Qhw
))
9208 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9209 dcb
.fOutxCtsFlow
= TRUE
;
9211 else if (EQ (tem
, Qsw
))
9216 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9218 /* Activate configuration. */
9219 if (!SetCommState (hnd
, &dcb
))
9220 error ("SetCommState() failed");
9222 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9223 pset_childp (p
, childp2
);
9229 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9233 struct timespec timeout
;
9234 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9235 int fd
= process
->infd
;
9237 n
= sys_read (fd
, (char*)buf
, sz
);
9244 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9245 if (err
== EWOULDBLOCK
)
9248 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9254 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9256 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9257 int fd
= process
->outfd
;
9258 ssize_t n
= sys_write (fd
, buf
, sz
);
9260 /* 0 or more bytes written means everything went fine. */
9264 /* Negative bytes written means we got an error in errno.
9265 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9266 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9267 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9271 #endif /* HAVE_GNUTLS */