1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2016 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #define DEFER_MS_W32_H
27 #include <mingw_time.h>
28 #include <stddef.h> /* for offsetof */
31 #include <float.h> /* for DBL_EPSILON */
38 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
40 #include <sys/utime.h>
43 /* Include (most) CRT headers *before* ms-w32.h. */
46 #include <string.h> /* for strerror, needed by sys_strerror */
47 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
73 char *sys_ctime (const time_t *);
74 int sys_chdir (const char *);
75 int sys_creat (const char *, int);
76 FILE *sys_fopen (const char *, const char *);
77 int sys_mkdir (const char *);
78 int sys_open (const char *, int, int);
79 int sys_rename (char const *, char const *);
80 int sys_rmdir (const char *);
82 int sys_dup2 (int, int);
83 int sys_read (int, char *, unsigned int);
84 int sys_write (int, const void *, unsigned int);
85 struct tm
*sys_localtime (const time_t *);
88 extern void dynlib_reset_last_error (void);
92 #include "epaths.h" /* for PATH_EXEC */
98 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
99 use a different name to avoid compilation problems. */
100 typedef struct _MEMORY_STATUS_EX
{
103 DWORDLONG ullTotalPhys
;
104 DWORDLONG ullAvailPhys
;
105 DWORDLONG ullTotalPageFile
;
106 DWORDLONG ullAvailPageFile
;
107 DWORDLONG ullTotalVirtual
;
108 DWORDLONG ullAvailVirtual
;
109 DWORDLONG ullAvailExtendedVirtual
;
110 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
112 /* These are here so that GDB would know about these data types. This
113 allows attaching GDB to Emacs when a fatal exception is triggered
114 and Windows pops up the "application needs to be closed" dialog.
115 At that point, _gnu_exception_handler, the top-level exception
116 handler installed by the MinGW startup code, is somewhere on the
117 call-stack of the main thread, so going to that call frame and
118 looking at the argument to _gnu_exception_handler, which is a
119 PEXCEPTION_POINTERS pointer, can reveal the exception code
120 (excptr->ExceptionRecord->ExceptionCode) and the address where the
121 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
122 well as some additional information specific to the exception. */
123 PEXCEPTION_POINTERS excptr
;
124 PEXCEPTION_RECORD excprec
;
130 #include <tlhelp32.h>
135 #if _WIN32_WINNT < 0x0500
136 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
137 /* This either is not in psapi.h or guarded by higher value of
138 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
139 defines it in psapi.h */
140 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
142 DWORD PageFaultCount
;
143 SIZE_T PeakWorkingSetSize
;
144 SIZE_T WorkingSetSize
;
145 SIZE_T QuotaPeakPagedPoolUsage
;
146 SIZE_T QuotaPagedPoolUsage
;
147 SIZE_T QuotaPeakNonPagedPoolUsage
;
148 SIZE_T QuotaNonPagedPoolUsage
;
149 SIZE_T PagefileUsage
;
150 SIZE_T PeakPagefileUsage
;
152 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
156 #include <winioctl.h>
163 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
164 define them by hand if not already defined. */
165 #ifndef SDDL_REVISION_1
166 #define SDDL_REVISION_1 1
167 #endif /* SDDL_REVISION_1 */
169 #if defined(_MSC_VER) || defined(MINGW_W64)
170 /* MSVC and MinGW64 don't provide the definition of
171 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
172 which cannot be included because it triggers conflicts with other
173 Windows API headers. So we define it here by hand. */
175 typedef struct _REPARSE_DATA_BUFFER
{
177 USHORT ReparseDataLength
;
181 USHORT SubstituteNameOffset
;
182 USHORT SubstituteNameLength
;
183 USHORT PrintNameOffset
;
184 USHORT PrintNameLength
;
187 } SymbolicLinkReparseBuffer
;
189 USHORT SubstituteNameOffset
;
190 USHORT SubstituteNameLength
;
191 USHORT PrintNameOffset
;
192 USHORT PrintNameLength
;
194 } MountPointReparseBuffer
;
197 } GenericReparseBuffer
;
199 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
201 #ifndef FILE_DEVICE_FILE_SYSTEM
202 #define FILE_DEVICE_FILE_SYSTEM 9
204 #ifndef METHOD_BUFFERED
205 #define METHOD_BUFFERED 0
207 #ifndef FILE_ANY_ACCESS
208 #define FILE_ANY_ACCESS 0x00000000
211 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
213 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
214 #ifndef FSCTL_GET_REPARSE_POINT
215 #define FSCTL_GET_REPARSE_POINT \
216 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
220 /* TCP connection support. */
221 #include <sys/socket.h>
240 #include <iphlpapi.h> /* should be after winsock2.h */
242 #include <wincrypt.h>
244 #include <c-strcase.h>
245 #include <utimens.h> /* for fdutimens */
249 #include "w32common.h"
250 #include "w32select.h"
251 #include "systime.h" /* for current_timespec, struct timespec */
252 #include "dispextern.h" /* for xstrcasecmp */
253 #include "coding.h" /* for Vlocale_coding_system */
255 #include "careadlinkat.h"
256 #include "allocator.h"
258 /* For Lisp_Process, serial_configure and serial_open. */
262 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
263 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
265 static DWORD
get_rid (PSID
);
266 static int is_symlink (const char *);
267 static char * chase_symlinks (const char *);
268 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
269 static int restore_privilege (TOKEN_PRIVILEGES
*);
270 static BOOL WINAPI
revert_to_self (void);
272 static int sys_access (const char *, int);
273 extern void *e_malloc (size_t);
274 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
275 const struct timespec
*, const sigset_t
*);
276 extern int sys_dup (int);
279 /* Initialization states.
281 WARNING: If you add any more such variables for additional APIs,
282 you MUST add initialization for them to globals_of_w32
283 below. This is because these variables might get set
284 to non-NULL values during dumping, but the dumped Emacs
285 cannot reuse those values, because it could be run on a
286 different version of the OS, where API addresses are
288 static BOOL g_b_init_is_windows_9x
;
289 static BOOL g_b_init_open_process_token
;
290 static BOOL g_b_init_get_token_information
;
291 static BOOL g_b_init_lookup_account_sid
;
292 static BOOL g_b_init_get_sid_sub_authority
;
293 static BOOL g_b_init_get_sid_sub_authority_count
;
294 static BOOL g_b_init_get_security_info
;
295 static BOOL g_b_init_get_file_security_w
;
296 static BOOL g_b_init_get_file_security_a
;
297 static BOOL g_b_init_get_security_descriptor_owner
;
298 static BOOL g_b_init_get_security_descriptor_group
;
299 static BOOL g_b_init_is_valid_sid
;
300 static BOOL g_b_init_create_toolhelp32_snapshot
;
301 static BOOL g_b_init_process32_first
;
302 static BOOL g_b_init_process32_next
;
303 static BOOL g_b_init_open_thread_token
;
304 static BOOL g_b_init_impersonate_self
;
305 static BOOL g_b_init_revert_to_self
;
306 static BOOL g_b_init_get_process_memory_info
;
307 static BOOL g_b_init_get_process_working_set_size
;
308 static BOOL g_b_init_global_memory_status
;
309 static BOOL g_b_init_global_memory_status_ex
;
310 static BOOL g_b_init_get_length_sid
;
311 static BOOL g_b_init_equal_sid
;
312 static BOOL g_b_init_copy_sid
;
313 static BOOL g_b_init_get_native_system_info
;
314 static BOOL g_b_init_get_system_times
;
315 static BOOL g_b_init_create_symbolic_link_w
;
316 static BOOL g_b_init_create_symbolic_link_a
;
317 static BOOL g_b_init_get_security_descriptor_dacl
;
318 static BOOL g_b_init_convert_sd_to_sddl
;
319 static BOOL g_b_init_convert_sddl_to_sd
;
320 static BOOL g_b_init_is_valid_security_descriptor
;
321 static BOOL g_b_init_set_file_security_w
;
322 static BOOL g_b_init_set_file_security_a
;
323 static BOOL g_b_init_set_named_security_info_w
;
324 static BOOL g_b_init_set_named_security_info_a
;
325 static BOOL g_b_init_get_adapters_info
;
327 BOOL g_b_init_compare_string_w
;
328 BOOL g_b_init_debug_break_process
;
331 BEGIN: Wrapper functions around OpenProcessToken
332 and other functions in advapi32.dll that are only
333 supported in Windows NT / 2k / XP
335 /* ** Function pointer typedefs ** */
336 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
337 HANDLE ProcessHandle
,
339 PHANDLE TokenHandle
);
340 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
342 TOKEN_INFORMATION_CLASS TokenInformationClass
,
343 LPVOID TokenInformation
,
344 DWORD TokenInformationLength
,
345 PDWORD ReturnLength
);
346 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
347 HANDLE process_handle
,
348 LPFILETIME creation_time
,
349 LPFILETIME exit_time
,
350 LPFILETIME kernel_time
,
351 LPFILETIME user_time
);
353 GetProcessTimes_Proc get_process_times_fn
= NULL
;
356 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
358 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
360 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
361 LPCTSTR lpSystemName
,
366 LPDWORD cbDomainName
,
367 PSID_NAME_USE peUse
);
368 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
371 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
373 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
375 SE_OBJECT_TYPE ObjectType
,
376 SECURITY_INFORMATION SecurityInfo
,
381 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
382 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
384 SECURITY_INFORMATION RequestedInformation
,
385 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
387 LPDWORD lpnLengthNeeded
);
388 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
390 SECURITY_INFORMATION RequestedInformation
,
391 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
393 LPDWORD lpnLengthNeeded
);
394 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
396 SECURITY_INFORMATION SecurityInformation
,
397 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
398 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
400 SECURITY_INFORMATION SecurityInformation
,
401 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
402 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
403 LPCWSTR lpObjectName
,
404 SE_OBJECT_TYPE ObjectType
,
405 SECURITY_INFORMATION SecurityInformation
,
410 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
412 SE_OBJECT_TYPE ObjectType
,
413 SECURITY_INFORMATION SecurityInformation
,
418 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
419 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
421 LPBOOL lpbOwnerDefaulted
);
422 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
423 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
425 LPBOOL lpbGroupDefaulted
);
426 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
427 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
428 LPBOOL lpbDaclPresent
,
430 LPBOOL lpbDaclDefaulted
);
431 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
433 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
435 DWORD th32ProcessID
);
436 typedef BOOL (WINAPI
* Process32First_Proc
) (
438 LPPROCESSENTRY32 lppe
);
439 typedef BOOL (WINAPI
* Process32Next_Proc
) (
441 LPPROCESSENTRY32 lppe
);
442 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
446 PHANDLE TokenHandle
);
447 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
448 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
449 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
450 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
452 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
454 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
456 PSIZE_T lpMinimumWorkingSetSize
,
457 PSIZE_T lpMaximumWorkingSetSize
);
458 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
459 LPMEMORYSTATUS lpBuffer
);
460 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
461 LPMEMORY_STATUS_EX lpBuffer
);
462 typedef BOOL (WINAPI
* CopySid_Proc
) (
463 DWORD nDestinationSidLength
,
464 PSID pDestinationSid
,
466 typedef BOOL (WINAPI
* EqualSid_Proc
) (
469 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
471 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
472 LPSYSTEM_INFO lpSystemInfo
);
473 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
474 LPFILETIME lpIdleTime
,
475 LPFILETIME lpKernelTime
,
476 LPFILETIME lpUserTime
);
477 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
478 LPCWSTR lpSymlinkFileName
,
479 LPCWSTR lpTargetFileName
,
481 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
482 LPCSTR lpSymlinkFileName
,
483 LPCSTR lpTargetFileName
,
485 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
486 LPCTSTR StringSecurityDescriptor
,
487 DWORD StringSDRevision
,
488 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
489 PULONG SecurityDescriptorSize
);
490 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
491 PSECURITY_DESCRIPTOR SecurityDescriptor
,
492 DWORD RequestedStringSDRevision
,
493 SECURITY_INFORMATION SecurityInformation
,
494 LPTSTR
*StringSecurityDescriptor
,
495 PULONG StringSecurityDescriptorLen
);
496 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
497 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
498 PIP_ADAPTER_INFO pAdapterInfo
,
501 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
502 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
503 DWORD multiByteToWideCharFlags
;
505 /* ** A utility function ** */
509 static BOOL s_b_ret
= 0;
510 OSVERSIONINFO os_ver
;
511 if (g_b_init_is_windows_9x
== 0)
513 g_b_init_is_windows_9x
= 1;
514 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
515 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
516 if (GetVersionEx (&os_ver
))
518 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
524 static Lisp_Object
ltime (ULONGLONG
);
526 /* Get total user and system times for get-internal-run-time.
527 Returns a list of integers if the times are provided by the OS
528 (NT derivatives), otherwise it returns the result of current-time. */
529 Lisp_Object
w32_get_internal_run_time (void);
532 w32_get_internal_run_time (void)
534 if (get_process_times_fn
)
536 FILETIME create
, exit
, kernel
, user
;
537 HANDLE proc
= GetCurrentProcess ();
538 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
540 LARGE_INTEGER user_int
, kernel_int
, total
;
541 user_int
.LowPart
= user
.dwLowDateTime
;
542 user_int
.HighPart
= user
.dwHighDateTime
;
543 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
544 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
545 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
546 return ltime (total
.QuadPart
);
550 return Fcurrent_time ();
553 /* ** The wrapper functions ** */
556 open_process_token (HANDLE ProcessHandle
,
560 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
561 HMODULE hm_advapi32
= NULL
;
562 if (is_windows_9x () == TRUE
)
566 if (g_b_init_open_process_token
== 0)
568 g_b_init_open_process_token
= 1;
569 hm_advapi32
= LoadLibrary ("Advapi32.dll");
570 s_pfn_Open_Process_Token
=
571 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
573 if (s_pfn_Open_Process_Token
== NULL
)
578 s_pfn_Open_Process_Token (
586 get_token_information (HANDLE TokenHandle
,
587 TOKEN_INFORMATION_CLASS TokenInformationClass
,
588 LPVOID TokenInformation
,
589 DWORD TokenInformationLength
,
592 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
593 HMODULE hm_advapi32
= NULL
;
594 if (is_windows_9x () == TRUE
)
598 if (g_b_init_get_token_information
== 0)
600 g_b_init_get_token_information
= 1;
601 hm_advapi32
= LoadLibrary ("Advapi32.dll");
602 s_pfn_Get_Token_Information
=
603 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
605 if (s_pfn_Get_Token_Information
== NULL
)
610 s_pfn_Get_Token_Information (
612 TokenInformationClass
,
614 TokenInformationLength
,
620 lookup_account_sid (LPCTSTR lpSystemName
,
625 LPDWORD cbDomainName
,
628 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
629 HMODULE hm_advapi32
= NULL
;
630 if (is_windows_9x () == TRUE
)
634 if (g_b_init_lookup_account_sid
== 0)
636 g_b_init_lookup_account_sid
= 1;
637 hm_advapi32
= LoadLibrary ("Advapi32.dll");
638 s_pfn_Lookup_Account_Sid
=
639 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
641 if (s_pfn_Lookup_Account_Sid
== NULL
)
646 s_pfn_Lookup_Account_Sid (
658 get_sid_sub_authority (PSID pSid
, DWORD n
)
660 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
661 static DWORD zero
= 0U;
662 HMODULE hm_advapi32
= NULL
;
663 if (is_windows_9x () == TRUE
)
667 if (g_b_init_get_sid_sub_authority
== 0)
669 g_b_init_get_sid_sub_authority
= 1;
670 hm_advapi32
= LoadLibrary ("Advapi32.dll");
671 s_pfn_Get_Sid_Sub_Authority
=
672 (GetSidSubAuthority_Proc
) GetProcAddress (
673 hm_advapi32
, "GetSidSubAuthority");
675 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
679 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
683 get_sid_sub_authority_count (PSID pSid
)
685 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
686 static UCHAR zero
= 0U;
687 HMODULE hm_advapi32
= NULL
;
688 if (is_windows_9x () == TRUE
)
692 if (g_b_init_get_sid_sub_authority_count
== 0)
694 g_b_init_get_sid_sub_authority_count
= 1;
695 hm_advapi32
= LoadLibrary ("Advapi32.dll");
696 s_pfn_Get_Sid_Sub_Authority_Count
=
697 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
698 hm_advapi32
, "GetSidSubAuthorityCount");
700 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
704 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
708 get_security_info (HANDLE handle
,
709 SE_OBJECT_TYPE ObjectType
,
710 SECURITY_INFORMATION SecurityInfo
,
715 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
717 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
718 HMODULE hm_advapi32
= NULL
;
719 if (is_windows_9x () == TRUE
)
723 if (g_b_init_get_security_info
== 0)
725 g_b_init_get_security_info
= 1;
726 hm_advapi32
= LoadLibrary ("Advapi32.dll");
727 s_pfn_Get_Security_Info
=
728 (GetSecurityInfo_Proc
) GetProcAddress (
729 hm_advapi32
, "GetSecurityInfo");
731 if (s_pfn_Get_Security_Info
== NULL
)
735 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
736 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
737 ppSecurityDescriptor
));
741 get_file_security (const char *lpFileName
,
742 SECURITY_INFORMATION RequestedInformation
,
743 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
745 LPDWORD lpnLengthNeeded
)
747 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
748 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
749 HMODULE hm_advapi32
= NULL
;
750 if (is_windows_9x () == TRUE
)
755 if (w32_unicode_filenames
)
757 wchar_t filename_w
[MAX_PATH
];
759 if (g_b_init_get_file_security_w
== 0)
761 g_b_init_get_file_security_w
= 1;
762 hm_advapi32
= LoadLibrary ("Advapi32.dll");
763 s_pfn_Get_File_SecurityW
=
764 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
767 if (s_pfn_Get_File_SecurityW
== NULL
)
772 filename_to_utf16 (lpFileName
, filename_w
);
773 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
774 pSecurityDescriptor
, nLength
,
779 char filename_a
[MAX_PATH
];
781 if (g_b_init_get_file_security_a
== 0)
783 g_b_init_get_file_security_a
= 1;
784 hm_advapi32
= LoadLibrary ("Advapi32.dll");
785 s_pfn_Get_File_SecurityA
=
786 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
789 if (s_pfn_Get_File_SecurityA
== NULL
)
794 filename_to_ansi (lpFileName
, filename_a
);
795 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
796 pSecurityDescriptor
, nLength
,
802 set_file_security (const char *lpFileName
,
803 SECURITY_INFORMATION SecurityInformation
,
804 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
806 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
807 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
808 HMODULE hm_advapi32
= NULL
;
809 if (is_windows_9x () == TRUE
)
814 if (w32_unicode_filenames
)
816 wchar_t filename_w
[MAX_PATH
];
818 if (g_b_init_set_file_security_w
== 0)
820 g_b_init_set_file_security_w
= 1;
821 hm_advapi32
= LoadLibrary ("Advapi32.dll");
822 s_pfn_Set_File_SecurityW
=
823 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
826 if (s_pfn_Set_File_SecurityW
== NULL
)
831 filename_to_utf16 (lpFileName
, filename_w
);
832 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
833 pSecurityDescriptor
));
837 char filename_a
[MAX_PATH
];
839 if (g_b_init_set_file_security_a
== 0)
841 g_b_init_set_file_security_a
= 1;
842 hm_advapi32
= LoadLibrary ("Advapi32.dll");
843 s_pfn_Set_File_SecurityA
=
844 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
847 if (s_pfn_Set_File_SecurityA
== NULL
)
852 filename_to_ansi (lpFileName
, filename_a
);
853 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
854 pSecurityDescriptor
));
859 set_named_security_info (LPCTSTR lpObjectName
,
860 SE_OBJECT_TYPE ObjectType
,
861 SECURITY_INFORMATION SecurityInformation
,
867 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
868 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
869 HMODULE hm_advapi32
= NULL
;
870 if (is_windows_9x () == TRUE
)
875 if (w32_unicode_filenames
)
877 wchar_t filename_w
[MAX_PATH
];
879 if (g_b_init_set_named_security_info_w
== 0)
881 g_b_init_set_named_security_info_w
= 1;
882 hm_advapi32
= LoadLibrary ("Advapi32.dll");
883 s_pfn_Set_Named_Security_InfoW
=
884 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
885 "SetNamedSecurityInfoW");
887 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
892 filename_to_utf16 (lpObjectName
, filename_w
);
893 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
894 SecurityInformation
, psidOwner
,
895 psidGroup
, pDacl
, pSacl
));
899 char filename_a
[MAX_PATH
];
901 if (g_b_init_set_named_security_info_a
== 0)
903 g_b_init_set_named_security_info_a
= 1;
904 hm_advapi32
= LoadLibrary ("Advapi32.dll");
905 s_pfn_Set_Named_Security_InfoA
=
906 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
907 "SetNamedSecurityInfoA");
909 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
914 filename_to_ansi (lpObjectName
, filename_a
);
915 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
916 SecurityInformation
, psidOwner
,
917 psidGroup
, pDacl
, pSacl
));
922 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
924 LPBOOL lpbOwnerDefaulted
)
926 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
927 HMODULE hm_advapi32
= NULL
;
928 if (is_windows_9x () == TRUE
)
933 if (g_b_init_get_security_descriptor_owner
== 0)
935 g_b_init_get_security_descriptor_owner
= 1;
936 hm_advapi32
= LoadLibrary ("Advapi32.dll");
937 s_pfn_Get_Security_Descriptor_Owner
=
938 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
939 hm_advapi32
, "GetSecurityDescriptorOwner");
941 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
946 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
951 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
953 LPBOOL lpbGroupDefaulted
)
955 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
956 HMODULE hm_advapi32
= NULL
;
957 if (is_windows_9x () == TRUE
)
962 if (g_b_init_get_security_descriptor_group
== 0)
964 g_b_init_get_security_descriptor_group
= 1;
965 hm_advapi32
= LoadLibrary ("Advapi32.dll");
966 s_pfn_Get_Security_Descriptor_Group
=
967 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
968 hm_advapi32
, "GetSecurityDescriptorGroup");
970 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
975 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
980 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
981 LPBOOL lpbDaclPresent
,
983 LPBOOL lpbDaclDefaulted
)
985 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
986 HMODULE hm_advapi32
= NULL
;
987 if (is_windows_9x () == TRUE
)
992 if (g_b_init_get_security_descriptor_dacl
== 0)
994 g_b_init_get_security_descriptor_dacl
= 1;
995 hm_advapi32
= LoadLibrary ("Advapi32.dll");
996 s_pfn_Get_Security_Descriptor_Dacl
=
997 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
998 hm_advapi32
, "GetSecurityDescriptorDacl");
1000 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
1005 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
1006 lpbDaclPresent
, pDacl
,
1011 is_valid_sid (PSID sid
)
1013 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
1014 HMODULE hm_advapi32
= NULL
;
1015 if (is_windows_9x () == TRUE
)
1019 if (g_b_init_is_valid_sid
== 0)
1021 g_b_init_is_valid_sid
= 1;
1022 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1023 s_pfn_Is_Valid_Sid
=
1024 (IsValidSid_Proc
) GetProcAddress (
1025 hm_advapi32
, "IsValidSid");
1027 if (s_pfn_Is_Valid_Sid
== NULL
)
1031 return (s_pfn_Is_Valid_Sid (sid
));
1035 equal_sid (PSID sid1
, PSID sid2
)
1037 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1038 HMODULE hm_advapi32
= NULL
;
1039 if (is_windows_9x () == TRUE
)
1043 if (g_b_init_equal_sid
== 0)
1045 g_b_init_equal_sid
= 1;
1046 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1048 (EqualSid_Proc
) GetProcAddress (
1049 hm_advapi32
, "EqualSid");
1051 if (s_pfn_Equal_Sid
== NULL
)
1055 return (s_pfn_Equal_Sid (sid1
, sid2
));
1059 get_length_sid (PSID sid
)
1061 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1062 HMODULE hm_advapi32
= NULL
;
1063 if (is_windows_9x () == TRUE
)
1067 if (g_b_init_get_length_sid
== 0)
1069 g_b_init_get_length_sid
= 1;
1070 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1071 s_pfn_Get_Length_Sid
=
1072 (GetLengthSid_Proc
) GetProcAddress (
1073 hm_advapi32
, "GetLengthSid");
1075 if (s_pfn_Get_Length_Sid
== NULL
)
1079 return (s_pfn_Get_Length_Sid (sid
));
1083 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1085 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1086 HMODULE hm_advapi32
= NULL
;
1087 if (is_windows_9x () == TRUE
)
1091 if (g_b_init_copy_sid
== 0)
1093 g_b_init_copy_sid
= 1;
1094 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1096 (CopySid_Proc
) GetProcAddress (
1097 hm_advapi32
, "CopySid");
1099 if (s_pfn_Copy_Sid
== NULL
)
1103 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1107 END: Wrapper functions around OpenProcessToken
1108 and other functions in advapi32.dll that are only
1109 supported in Windows NT / 2k / XP
1113 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1115 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1116 if (is_windows_9x () != TRUE
)
1118 if (g_b_init_get_native_system_info
== 0)
1120 g_b_init_get_native_system_info
= 1;
1121 s_pfn_Get_Native_System_Info
=
1122 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1123 "GetNativeSystemInfo");
1125 if (s_pfn_Get_Native_System_Info
!= NULL
)
1126 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1129 lpSystemInfo
->dwNumberOfProcessors
= -1;
1133 get_system_times (LPFILETIME lpIdleTime
,
1134 LPFILETIME lpKernelTime
,
1135 LPFILETIME lpUserTime
)
1137 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1138 if (is_windows_9x () == TRUE
)
1142 if (g_b_init_get_system_times
== 0)
1144 g_b_init_get_system_times
= 1;
1145 s_pfn_Get_System_times
=
1146 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1149 if (s_pfn_Get_System_times
== NULL
)
1151 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1154 static BOOLEAN WINAPI
1155 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1156 LPCSTR lpTargetFileName
,
1159 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1160 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1163 if (is_windows_9x () == TRUE
)
1168 if (w32_unicode_filenames
)
1170 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1172 if (g_b_init_create_symbolic_link_w
== 0)
1174 g_b_init_create_symbolic_link_w
= 1;
1175 s_pfn_Create_Symbolic_LinkW
=
1176 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1177 "CreateSymbolicLinkW");
1179 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1185 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1186 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1187 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1188 /* If we were denied creation of the symlink, try again after
1189 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1192 TOKEN_PRIVILEGES priv_current
;
1194 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1197 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1198 restore_privilege (&priv_current
);
1205 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1207 if (g_b_init_create_symbolic_link_a
== 0)
1209 g_b_init_create_symbolic_link_a
= 1;
1210 s_pfn_Create_Symbolic_LinkA
=
1211 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1212 "CreateSymbolicLinkA");
1214 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1220 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1221 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1222 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1223 /* If we were denied creation of the symlink, try again after
1224 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1227 TOKEN_PRIVILEGES priv_current
;
1229 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1232 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1233 restore_privilege (&priv_current
);
1242 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1244 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1246 if (is_windows_9x () == TRUE
)
1252 if (g_b_init_is_valid_security_descriptor
== 0)
1254 g_b_init_is_valid_security_descriptor
= 1;
1255 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1256 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1257 "IsValidSecurityDescriptor");
1259 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1265 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1269 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1270 DWORD RequestedStringSDRevision
,
1271 SECURITY_INFORMATION SecurityInformation
,
1272 LPTSTR
*StringSecurityDescriptor
,
1273 PULONG StringSecurityDescriptorLen
)
1275 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1278 if (is_windows_9x () == TRUE
)
1284 if (g_b_init_convert_sd_to_sddl
== 0)
1286 g_b_init_convert_sd_to_sddl
= 1;
1288 s_pfn_Convert_SD_To_SDDL
=
1289 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1290 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1292 s_pfn_Convert_SD_To_SDDL
=
1293 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1294 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1297 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1303 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1304 RequestedStringSDRevision
,
1305 SecurityInformation
,
1306 StringSecurityDescriptor
,
1307 StringSecurityDescriptorLen
);
1313 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1314 DWORD StringSDRevision
,
1315 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1316 PULONG SecurityDescriptorSize
)
1318 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1321 if (is_windows_9x () == TRUE
)
1327 if (g_b_init_convert_sddl_to_sd
== 0)
1329 g_b_init_convert_sddl_to_sd
= 1;
1331 s_pfn_Convert_SDDL_To_SD
=
1332 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1333 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1335 s_pfn_Convert_SDDL_To_SD
=
1336 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1337 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1340 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1346 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1349 SecurityDescriptorSize
);
1355 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1357 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1358 HMODULE hm_iphlpapi
= NULL
;
1360 if (is_windows_9x () == TRUE
)
1361 return ERROR_NOT_SUPPORTED
;
1363 if (g_b_init_get_adapters_info
== 0)
1365 g_b_init_get_adapters_info
= 1;
1366 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1368 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1369 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1371 if (s_pfn_Get_Adapters_Info
== NULL
)
1372 return ERROR_NOT_SUPPORTED
;
1373 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1378 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1379 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1381 This is called from alloc.c:valid_pointer_p. */
1383 w32_valid_pointer_p (void *p
, int size
)
1386 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1390 unsigned char *buf
= alloca (size
);
1391 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1402 /* Here's an overview of how the Windows build supports file names
1403 that cannot be encoded by the current system codepage.
1405 From the POV of Lisp and layers of C code above the functions here,
1406 Emacs on Windows pretends that its file names are encoded in UTF-8;
1407 see encode_file and decode_file on coding.c. Any file name that is
1408 passed as a unibyte string to C functions defined here is assumed
1409 to be in UTF-8 encoding. Any file name returned by functions
1410 defined here must be in UTF-8 encoding, with only a few exceptions
1411 reserved for a couple of special cases. (Be sure to use
1412 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1413 as they can be much longer than MAX_PATH!)
1415 The UTF-8 encoded file names cannot be passed to system APIs, as
1416 Windows does not support that. Therefore, they are converted
1417 either to UTF-16 or to the ANSI codepage, depending on the value of
1418 w32-unicode-filenames, before calling any system APIs or CRT library
1419 functions. The default value of that variable is determined by the
1420 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1421 user can change that default (although I don't see why would she
1424 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1425 filename_from_utf16, and filename_from_ansi, are the workhorses of
1426 these conversions. They rely on Windows native APIs
1427 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1428 functions from coding.c here, because they allocate memory, which
1429 is a bad idea on the level of libc, which is what the functions
1430 here emulate. (If you worry about performance due to constant
1431 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1432 it was measured to take only a few microseconds on a not-so-fast
1433 machine, and second, that's exactly what the ANSI APIs we used
1434 before did anyway, because they are just thin wrappers around the
1437 The variables file-name-coding-system and default-file-name-coding-system
1438 still exist, but are actually used only when a file name needs to
1439 be converted to the ANSI codepage. This happens all the time when
1440 w32-unicode-filenames is nil, but can also happen from time to time
1441 when it is t. Otherwise, these variables have no effect on file-name
1442 encoding when w32-unicode-filenames is t; this is similar to
1443 selection-coding-system.
1445 This arrangement works very well, but it has a few gotchas and
1448 . Lisp code that encodes or decodes file names manually should
1449 normally use 'utf-8' as the coding-system on Windows,
1450 disregarding file-name-coding-system. This is a somewhat
1451 unpleasant consequence, but it cannot be avoided. Fortunately,
1452 very few Lisp packages need to do that.
1454 More generally, passing to library functions (e.g., fopen or
1455 opendir) file names already encoded in the ANSI codepage is
1456 explicitly *verboten*, as all those functions, as shadowed and
1457 emulated here, assume they will receive UTF-8 encoded file names.
1459 For the same reasons, no CRT function or Win32 API can be called
1460 directly in Emacs sources, without either converting the file
1461 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1462 some shadowing function defined here.
1464 . Environment variables stored in Vprocess_environment are encoded
1465 in the ANSI codepage, so if getenv/egetenv is used for a variable
1466 whose value is a file name or a list of directories, it needs to
1467 be converted to UTF-8, before it is used as argument to functions
1468 or decoded into a Lisp string.
1470 . File names passed to external libraries, like the image libraries
1471 and GnuTLS, need special handling. These libraries generally
1472 don't support UTF-16 or UTF-8 file names, so they must get file
1473 names encoded in the ANSI codepage. To facilitate using these
1474 libraries with file names that are not encodable in the ANSI
1475 codepage, use the function ansi_encode_filename, which will try
1476 to use the short 8+3 alias of a file name if that file name is
1477 not encodable in the ANSI codepage. See image.c and gnutls.c for
1478 examples of how this should be done.
1480 . Running subprocesses in non-ASCII directories and with non-ASCII
1481 file arguments is limited to the current codepage (even though
1482 Emacs is perfectly capable of finding an executable program file
1483 in a directory whose name cannot be encoded in the current
1484 codepage). This is because the command-line arguments are
1485 encoded _before_ they get to the w32-specific level, and the
1486 encoding is not known in advance (it doesn't have to be the
1487 current ANSI codepage), so w32proc.c functions cannot re-encode
1488 them in UTF-16. This should be fixed, but will also require
1489 changes in cmdproxy. The current limitation is not terribly bad
1490 anyway, since very few, if any, Windows console programs that are
1491 likely to be invoked by Emacs support UTF-16 encoded command
1494 . For similar reasons, server.el and emacsclient are also limited
1495 to the current ANSI codepage for now.
1497 . Emacs itself can only handle command-line arguments encoded in
1498 the current codepage.
1500 . Turning on w32-unicode-filename on Windows 9X (if it at all
1501 works) requires UNICOWS.DLL, which is thus a requirement even in
1502 non-GUI sessions, something the we previously avoided. */
1506 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1507 codepage defined by file-name-coding-system. */
1509 /* Current codepage for encoding file names. */
1510 static int file_name_codepage
;
1512 /* Initialize the codepage used for decoding file names. This is
1513 needed to undo the value recorded during dumping, which might not
1514 be correct when we run the dumped Emacs. */
1516 w32_init_file_name_codepage (void)
1518 file_name_codepage
= CP_ACP
;
1519 w32_ansi_code_page
= CP_ACP
;
1522 /* Produce a Windows ANSI codepage suitable for encoding file names.
1523 Return the information about that codepage in CP_INFO. */
1525 codepage_for_filenames (CPINFO
*cp_info
)
1527 /* A simple cache to avoid calling GetCPInfo every time we need to
1528 encode/decode a file name. The file-name encoding is not
1529 supposed to be changed too frequently, if ever. */
1530 static Lisp_Object last_file_name_encoding
;
1532 Lisp_Object current_encoding
;
1534 current_encoding
= Vfile_name_coding_system
;
1535 if (NILP (current_encoding
))
1536 current_encoding
= Vdefault_file_name_coding_system
;
1538 if (!EQ (last_file_name_encoding
, current_encoding
)
1539 || NILP (last_file_name_encoding
))
1541 /* Default to the current ANSI codepage. */
1542 file_name_codepage
= w32_ansi_code_page
;
1544 if (!NILP (current_encoding
))
1546 char *cpname
= SSDATA (SYMBOL_NAME (current_encoding
));
1547 char *cp
= NULL
, *end
;
1550 if (strncmp (cpname
, "cp", 2) == 0)
1552 else if (strncmp (cpname
, "windows-", 8) == 0)
1558 cpnum
= strtol (cp
, &end
, 10);
1559 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1560 file_name_codepage
= cpnum
;
1564 if (!file_name_codepage
)
1565 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1567 if (!GetCPInfo (file_name_codepage
, &cp
))
1569 file_name_codepage
= CP_ACP
;
1570 if (!GetCPInfo (file_name_codepage
, &cp
))
1574 /* Cache the new value. */
1575 last_file_name_encoding
= current_encoding
;
1580 return file_name_codepage
;
1584 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1586 int result
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, fn_in
,
1587 -1, fn_out
, MAX_PATH
);
1591 DWORD err
= GetLastError ();
1595 case ERROR_INVALID_FLAGS
:
1596 case ERROR_INVALID_PARAMETER
:
1599 case ERROR_INSUFFICIENT_BUFFER
:
1600 case ERROR_NO_UNICODE_TRANSLATION
:
1611 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1613 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1614 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1618 DWORD err
= GetLastError ();
1622 case ERROR_INVALID_FLAGS
:
1623 case ERROR_INVALID_PARAMETER
:
1626 case ERROR_INSUFFICIENT_BUFFER
:
1627 case ERROR_NO_UNICODE_TRANSLATION
:
1638 filename_to_ansi (const char *fn_in
, char *fn_out
)
1640 wchar_t fn_utf16
[MAX_PATH
];
1642 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1645 int codepage
= codepage_for_filenames (NULL
);
1647 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1648 fn_out
, MAX_PATH
, NULL
, NULL
);
1651 DWORD err
= GetLastError ();
1655 case ERROR_INVALID_FLAGS
:
1656 case ERROR_INVALID_PARAMETER
:
1659 case ERROR_INSUFFICIENT_BUFFER
:
1660 case ERROR_NO_UNICODE_TRANSLATION
:
1673 filename_from_ansi (const char *fn_in
, char *fn_out
)
1675 wchar_t fn_utf16
[MAX_PATH
];
1676 int codepage
= codepage_for_filenames (NULL
);
1677 int result
= pMultiByteToWideChar (codepage
, multiByteToWideCharFlags
, fn_in
,
1678 -1, fn_utf16
, MAX_PATH
);
1682 DWORD err
= GetLastError ();
1686 case ERROR_INVALID_FLAGS
:
1687 case ERROR_INVALID_PARAMETER
:
1690 case ERROR_INSUFFICIENT_BUFFER
:
1691 case ERROR_NO_UNICODE_TRANSLATION
:
1698 return filename_from_utf16 (fn_utf16
, fn_out
);
1703 /* The directory where we started, in UTF-8. */
1704 static char startup_dir
[MAX_UTF8_PATH
];
1706 /* Get the current working directory. */
1708 getcwd (char *dir
, int dirsize
)
1715 if (dirsize
<= strlen (startup_dir
))
1721 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1725 /* Emacs doesn't actually change directory itself, it stays in the
1726 same directory where it was started. */
1727 strcpy (dir
, startup_dir
);
1732 /* Emulate getloadavg. */
1734 struct load_sample
{
1741 /* Number of processors on this machine. */
1742 static unsigned num_of_processors
;
1744 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1745 static struct load_sample samples
[16*60];
1746 static int first_idx
= -1, last_idx
= -1;
1747 static int max_idx
= ARRAYELTS (samples
);
1752 int next_idx
= from
+ 1;
1754 if (next_idx
>= max_idx
)
1763 int prev_idx
= from
- 1;
1766 prev_idx
= max_idx
- 1;
1772 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1774 SYSTEM_INFO sysinfo
;
1775 FILETIME ft_idle
, ft_user
, ft_kernel
;
1777 /* Initialize the number of processors on this machine. */
1778 if (num_of_processors
<= 0)
1780 get_native_system_info (&sysinfo
);
1781 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1782 if (num_of_processors
<= 0)
1784 GetSystemInfo (&sysinfo
);
1785 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1787 if (num_of_processors
<= 0)
1788 num_of_processors
= 1;
1791 /* TODO: Take into account threads that are ready to run, by
1792 sampling the "\System\Processor Queue Length" performance
1793 counter. The code below accounts only for threads that are
1794 actually running. */
1796 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1798 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1800 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1801 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1802 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1803 *idle
= uidle
.QuadPart
;
1804 *kernel
= ukernel
.QuadPart
;
1805 *user
= uuser
.QuadPart
;
1815 /* Produce the load average for a given time interval, using the
1816 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1817 1-minute, 5-minute, or 15-minute average, respectively. */
1821 double retval
= -1.0;
1824 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1825 time_t now
= samples
[last_idx
].sample_time
;
1827 if (first_idx
!= last_idx
)
1829 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1831 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1832 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1835 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1836 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1837 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1839 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1842 if (idx
== first_idx
)
1851 getloadavg (double loadavg
[], int nelem
)
1854 ULONGLONG idle
, kernel
, user
;
1855 time_t now
= time (NULL
);
1857 /* If system time jumped back for some reason, delete all samples
1858 whose time is later than the current wall-clock time. This
1859 prevents load average figures from becoming frozen for prolonged
1860 periods of time, when system time is reset backwards. */
1863 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1865 if (last_idx
== first_idx
)
1867 first_idx
= last_idx
= -1;
1870 last_idx
= buf_prev (last_idx
);
1874 /* Store another sample. We ignore samples that are less than 1 sec
1877 || (difftime (now
, samples
[last_idx
].sample_time
)
1878 >= 1.0 - 2*DBL_EPSILON
*now
))
1880 sample_system_load (&idle
, &kernel
, &user
);
1881 last_idx
= buf_next (last_idx
);
1882 samples
[last_idx
].sample_time
= now
;
1883 samples
[last_idx
].idle
= idle
;
1884 samples
[last_idx
].kernel
= kernel
;
1885 samples
[last_idx
].user
= user
;
1886 /* If the buffer has more that 15 min worth of samples, discard
1888 if (first_idx
== -1)
1889 first_idx
= last_idx
;
1890 while (first_idx
!= last_idx
1891 && (difftime (now
, samples
[first_idx
].sample_time
)
1892 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1893 first_idx
= buf_next (first_idx
);
1896 for (elem
= 0; elem
< nelem
; elem
++)
1898 double avg
= getavg (elem
);
1902 loadavg
[elem
] = avg
;
1908 /* Emulate getpwuid, getpwnam and others. */
1910 #define PASSWD_FIELD_SIZE 256
1912 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1913 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1914 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1915 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1916 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1918 static struct passwd dflt_passwd
=
1930 static char dflt_group_name
[GNLEN
+1];
1932 static struct group dflt_group
=
1934 /* When group information is not available, we return this as the
1935 group for all files. */
1943 return dflt_passwd
.pw_uid
;
1949 /* I could imagine arguing for checking to see whether the user is
1950 in the Administrators group and returning a UID of 0 for that
1951 case, but I don't know how wise that would be in the long run. */
1958 return dflt_passwd
.pw_gid
;
1968 getpwuid (unsigned uid
)
1970 if (uid
== dflt_passwd
.pw_uid
)
1971 return &dflt_passwd
;
1976 getgrgid (gid_t gid
)
1982 getpwnam (char *name
)
1986 pw
= getpwuid (getuid ());
1990 if (xstrcasecmp (name
, pw
->pw_name
))
1997 init_user_info (void)
1999 /* Find the user's real name by opening the process token and
2000 looking up the name associated with the user-sid in that token.
2002 Use the relative portion of the identifier authority value from
2003 the user-sid as the user id value (same for group id using the
2004 primary group sid from the process token). */
2006 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
2007 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
2008 DWORD glength
= sizeof (gname
);
2009 HANDLE token
= NULL
;
2010 SID_NAME_USE user_type
;
2011 unsigned char *buf
= NULL
;
2013 TOKEN_USER user_token
;
2014 TOKEN_PRIMARY_GROUP group_token
;
2017 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
2020 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
2021 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2023 buf
= xmalloc (blen
);
2024 result
= get_token_information (token
, TokenUser
,
2025 (LPVOID
)buf
, blen
, &needed
);
2028 memcpy (&user_token
, buf
, sizeof (user_token
));
2029 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
2031 domain
, &dlength
, &user_type
);
2039 strcpy (dflt_passwd
.pw_name
, uname
);
2040 /* Determine a reasonable uid value. */
2041 if (xstrcasecmp ("administrator", uname
) == 0)
2043 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2044 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2048 /* Use the last sub-authority value of the RID, the relative
2049 portion of the SID, as user/group ID. */
2050 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2052 /* Get group id and name. */
2053 result
= get_token_information (token
, TokenPrimaryGroup
,
2054 (LPVOID
)buf
, blen
, &needed
);
2055 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2057 buf
= xrealloc (buf
, blen
= needed
);
2058 result
= get_token_information (token
, TokenPrimaryGroup
,
2059 (LPVOID
)buf
, blen
, &needed
);
2063 memcpy (&group_token
, buf
, sizeof (group_token
));
2064 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2065 dlength
= sizeof (domain
);
2066 /* If we can get at the real Primary Group name, use that.
2067 Otherwise, the default group name was already set to
2068 "None" in globals_of_w32. */
2069 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2070 gname
, &glength
, NULL
, &dlength
,
2072 strcpy (dflt_group_name
, gname
);
2075 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2078 /* If security calls are not supported (presumably because we
2079 are running under Windows 9X), fallback to this: */
2080 else if (GetUserName (uname
, &ulength
))
2082 strcpy (dflt_passwd
.pw_name
, uname
);
2083 if (xstrcasecmp ("administrator", uname
) == 0)
2084 dflt_passwd
.pw_uid
= 0;
2086 dflt_passwd
.pw_uid
= 123;
2087 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2091 strcpy (dflt_passwd
.pw_name
, "unknown");
2092 dflt_passwd
.pw_uid
= 123;
2093 dflt_passwd
.pw_gid
= 123;
2095 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2097 /* Set dir and shell from environment variables. */
2098 if (w32_unicode_filenames
)
2100 wchar_t *home
= _wgetenv (L
"HOME");
2101 wchar_t *shell
= _wgetenv (L
"SHELL");
2103 /* Ensure HOME and SHELL are defined. */
2108 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2109 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2113 char *home
= getenv ("HOME");
2114 char *shell
= getenv ("SHELL");
2120 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2121 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2126 CloseHandle (token
);
2129 static HCRYPTPROV w32_crypto_hprov
;
2131 w32_init_crypt_random (void)
2133 if (!CryptAcquireContext (&w32_crypto_hprov
, NULL
, NULL
, PROV_RSA_FULL
,
2134 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
2136 DebPrint (("CryptAcquireContext failed with error %x\n",
2138 w32_crypto_hprov
= 0;
2145 w32_init_random (void *buf
, ptrdiff_t buflen
)
2147 if (!w32_crypto_hprov
)
2148 w32_init_crypt_random ();
2149 if (w32_crypto_hprov
)
2151 if (CryptGenRandom (w32_crypto_hprov
, buflen
, (BYTE
*)buf
))
2160 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2161 return ((rand () << 15) | rand ());
2170 /* Return the maximum length in bytes of a multibyte character
2171 sequence encoded in the current ANSI codepage. This is required to
2172 correctly walk the encoded file names one character at a time. */
2174 max_filename_mbslen (void)
2178 codepage_for_filenames (&cp_info
);
2179 return cp_info
.MaxCharSize
;
2182 /* Normalize filename by converting in-place all of its path
2183 separators to the separator specified by PATH_SEP. */
2186 normalize_filename (register char *fp
, char path_sep
)
2190 /* Always lower-case drive letters a-z, even if the filesystem
2191 preserves case in filenames.
2192 This is so filenames can be compared by string comparison
2193 functions that are case-sensitive. Even case-preserving filesystems
2194 do not distinguish case in drive letters. */
2197 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2205 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2211 /* Destructively turn backslashes into slashes. */
2213 dostounix_filename (register char *p
)
2215 normalize_filename (p
, '/');
2218 /* Destructively turn slashes into backslashes. */
2220 unixtodos_filename (register char *p
)
2222 normalize_filename (p
, '\\');
2225 /* Remove all CR's that are followed by a LF.
2226 (From msdos.c...probably should figure out a way to share it,
2227 although this code isn't going to ever change.) */
2229 crlf_to_lf (register int n
, register char *buf
)
2231 unsigned char *np
= (unsigned char *)buf
;
2232 unsigned char *startp
= np
;
2233 char *endp
= buf
+ n
;
2237 while (buf
< endp
- 1)
2241 if (*(++buf
) != 0x0a)
2252 /* Parse the root part of file name, if present. Return length and
2253 optionally store pointer to char after root. */
2255 parse_root (const char * name
, const char ** pPath
)
2257 const char * start
= name
;
2262 /* find the root name of the volume if given */
2263 if (isalpha (name
[0]) && name
[1] == ':')
2265 /* skip past drive specifier */
2267 if (IS_DIRECTORY_SEP (name
[0]))
2270 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2277 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2282 if (IS_DIRECTORY_SEP (name
[0]))
2289 return name
- start
;
2292 /* Get long base name for name; name is assumed to be absolute. */
2294 get_long_basename (char * name
, char * buf
, int size
)
2296 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2297 char fname_utf8
[MAX_UTF8_PATH
];
2301 /* Must be valid filename, no wild cards or other invalid characters. */
2302 if (strpbrk (name
, "*?|<>\""))
2305 if (w32_unicode_filenames
)
2307 wchar_t fname_utf16
[MAX_PATH
];
2308 WIN32_FIND_DATAW find_data_wide
;
2310 filename_to_utf16 (name
, fname_utf16
);
2311 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2312 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2313 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2317 char fname_ansi
[MAX_PATH
];
2318 WIN32_FIND_DATAA find_data_ansi
;
2320 filename_to_ansi (name
, fname_ansi
);
2321 /* If the ANSI name includes ? characters, it is not encodable
2322 in the ANSI codepage. In that case, we deliver the question
2323 marks to the caller; calling FindFirstFileA in this case
2324 could return some unrelated file name in the same
2326 if (_mbspbrk (fname_ansi
, "?"))
2328 /* Find the basename of fname_ansi. */
2329 char *p
= strrchr (fname_ansi
, '\\');
2335 cstatus
= filename_from_ansi (p
, fname_utf8
);
2339 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2340 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2341 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2345 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2346 memcpy (buf
, fname_utf8
, len
+ 1);
2350 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2351 FindClose (dir_handle
);
2356 /* Get long name for file, if possible (assumed to be absolute). */
2358 w32_get_long_filename (const char * name
, char * buf
, int size
)
2363 char full
[ MAX_UTF8_PATH
];
2366 len
= strlen (name
);
2367 if (len
>= MAX_UTF8_PATH
)
2370 /* Use local copy for destructive modification. */
2371 memcpy (full
, name
, len
+1);
2372 unixtodos_filename (full
);
2374 /* Copy root part verbatim. */
2375 len
= parse_root (full
, (const char **)&p
);
2376 memcpy (o
, full
, len
);
2381 while (p
!= NULL
&& *p
)
2384 p
= strchr (q
, '\\');
2386 len
= get_long_basename (full
, o
, size
);
2409 w32_get_short_filename (const char * name
, char * buf
, int size
)
2411 if (w32_unicode_filenames
)
2413 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2414 unsigned int retval
;
2416 filename_to_utf16 (name
, name_utf16
);
2417 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2418 if (retval
&& retval
< size
)
2419 filename_from_utf16 (short_name
, buf
);
2424 char name_ansi
[MAX_PATH
];
2426 filename_to_ansi (name
, name_ansi
);
2427 return GetShortPathNameA (name_ansi
, buf
, size
);
2431 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2432 MS-Windows ANSI codepage. If FILENAME includes characters not
2433 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2434 if it exists. This is needed because the w32 build wants to
2435 support file names outside of the system locale, but image
2436 libraries typically don't support wide (a.k.a. "Unicode") APIs
2437 required for that. */
2440 ansi_encode_filename (Lisp_Object filename
)
2442 Lisp_Object encoded_filename
;
2443 char fname
[MAX_PATH
];
2445 filename_to_ansi (SSDATA (filename
), fname
);
2446 if (_mbspbrk (fname
, "?"))
2448 char shortname
[MAX_PATH
];
2450 if (w32_get_short_filename (SSDATA (filename
), shortname
, MAX_PATH
))
2452 dostounix_filename (shortname
);
2453 encoded_filename
= build_string (shortname
);
2456 encoded_filename
= build_unibyte_string (fname
);
2459 encoded_filename
= build_unibyte_string (fname
);
2460 return encoded_filename
;
2464 is_unc_volume (const char *filename
)
2466 const char *ptr
= filename
;
2468 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2471 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2477 /* Emulate the Posix unsetenv. */
2479 unsetenv (const char *name
)
2484 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2489 name_len
= strlen (name
);
2490 /* MS docs says an environment variable cannot be longer than 32K. */
2491 if (name_len
> 32767)
2496 /* It is safe to use 'alloca' with 32K size, since the stack is at
2497 least 2MB, and we set it to 8MB in the link command line. */
2498 var
= alloca (name_len
+ 2);
2499 strncpy (var
, name
, name_len
);
2500 var
[name_len
++] = '=';
2501 var
[name_len
] = '\0';
2502 return _putenv (var
);
2505 /* MS _putenv doesn't support removing a variable when the argument
2506 does not include the '=' character, so we fix that here. */
2508 sys_putenv (char *str
)
2510 const char *const name_end
= strchr (str
, '=');
2512 if (name_end
== NULL
)
2514 /* Remove the variable from the environment. */
2515 return unsetenv (str
);
2518 if (strncmp (str
, "TZ=<", 4) == 0)
2520 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2521 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2522 and to the undocumented placeholder "ZZZ" otherwise. */
2523 bool supported_abbr
= true;
2524 for (char *p
= str
+ 4; *p
; p
++)
2526 if (('0' <= *p
&& *p
<= '9') || *p
== '-' || *p
== '+')
2527 supported_abbr
= false;
2533 abbrlen
= p
- (str
+ 4);
2534 memmove (str
+ 3, str
+ 4, abbrlen
);
2539 memset (str
+ 3, 'Z', abbrlen
);
2541 memmove (str
+ 3 + abbrlen
, p
+ 1, strlen (p
));
2547 return _putenv (str
);
2550 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2553 w32_get_resource (const char *key
, LPDWORD lpdwtype
)
2556 HKEY hrootkey
= NULL
;
2559 /* Check both the current user and the local machine to see if
2560 we have any resources. */
2562 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2566 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2567 && (lpvalue
= xmalloc (cbData
)) != NULL
2568 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2570 RegCloseKey (hrootkey
);
2576 RegCloseKey (hrootkey
);
2579 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2583 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2584 && (lpvalue
= xmalloc (cbData
)) != NULL
2585 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2587 RegCloseKey (hrootkey
);
2593 RegCloseKey (hrootkey
);
2599 /* The argv[] array holds ANSI-encoded strings, and so this function
2600 works with ANS_encoded strings. */
2602 init_environment (char ** argv
)
2604 static const char * const tempdirs
[] = {
2605 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2610 const int imax
= ARRAYELTS (tempdirs
);
2612 /* Implementation note: This function explicitly works with ANSI
2613 file names, not with UTF-8 encoded file names. This is because
2614 this function pushes variables into the Emacs's environment, and
2615 the environment variables are always assumed to be in the
2616 locale-specific encoding. Do NOT call any functions that accept
2617 UTF-8 file names from this function! */
2619 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2620 temporary files and assume "/tmp" if $TMPDIR is unset, which
2621 will break on DOS/Windows. Refuse to work if we cannot find
2622 a directory, not even "c:/", usable for that purpose. */
2623 for (i
= 0; i
< imax
; i
++)
2625 const char *tmp
= tempdirs
[i
];
2628 tmp
= getenv (tmp
+ 1);
2629 /* Note that `access' can lie to us if the directory resides on a
2630 read-only filesystem, like CD-ROM or a write-protected floppy.
2631 The only way to be really sure is to actually create a file and
2632 see if it succeeds. But I think that's too much to ask. */
2634 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2635 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2637 char * var
= alloca (strlen (tmp
) + 8);
2638 sprintf (var
, "TMPDIR=%s", tmp
);
2639 _putenv (strdup (var
));
2646 Fcons (build_string ("no usable temporary directories found!!"),
2648 "While setting TMPDIR: ");
2650 /* Check for environment variables and use registry settings if they
2651 don't exist. Fallback on default values where applicable. */
2656 char locale_name
[32];
2657 char default_home
[MAX_PATH
];
2660 static const struct env_entry
2663 const char * def_value
;
2666 /* If the default value is NULL, we will use the value from the
2667 outside environment or the Registry, but will not push the
2668 variable into the Emacs environment if it is defined neither
2669 in the Registry nor in the outside environment. */
2671 {"PRELOAD_WINSOCK", NULL
},
2672 {"emacs_dir", "C:/emacs"},
2673 {"EMACSLOADPATH", NULL
},
2674 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2675 {"EMACSDATA", NULL
},
2676 {"EMACSPATH", NULL
},
2683 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2685 /* We need to copy dflt_envvars[] and work on the copy because we
2686 don't want the dumped Emacs to inherit the values of
2687 environment variables we saw during dumping (which could be on
2688 a different system). The defaults above must be left intact. */
2689 struct env_entry env_vars
[N_ENV_VARS
];
2691 for (i
= 0; i
< N_ENV_VARS
; i
++)
2692 env_vars
[i
] = dflt_envvars
[i
];
2694 /* For backwards compatibility, check if a .emacs file exists in C:/
2695 If not, then we can try to default to the appdata directory under the
2696 user's profile, which is more likely to be writable. */
2697 if (sys_access ("C:/.emacs", F_OK
) != 0)
2699 HRESULT profile_result
;
2700 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2701 of Windows 95 and NT4 that have not been updated to include
2703 ShGetFolderPath_fn get_folder_path
;
2704 get_folder_path
= (ShGetFolderPath_fn
)
2705 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2707 if (get_folder_path
!= NULL
)
2709 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2712 /* If we can't get the appdata dir, revert to old behavior. */
2713 if (profile_result
== S_OK
)
2715 env_vars
[0].def_value
= default_home
;
2721 /* Get default locale info and use it for LANG. */
2722 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2723 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2724 locale_name
, sizeof (locale_name
)))
2726 for (i
= 0; i
< N_ENV_VARS
; i
++)
2728 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2730 env_vars
[i
].def_value
= locale_name
;
2736 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2738 /* Treat emacs_dir specially: set it unconditionally based on our
2742 char modname
[MAX_PATH
];
2744 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2746 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2750 if ((p
= _mbsrchr (modname
, '\\'))
2751 /* From bin means installed Emacs, from src means uninstalled. */
2752 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2754 char buf
[SET_ENV_BUF_SIZE
];
2755 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2758 for (p
= modname
; *p
; p
= CharNext (p
))
2759 if (*p
== '\\') *p
= '/';
2761 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2762 _putenv (strdup (buf
));
2763 /* If we are running from the Posix-like build tree, define
2764 SHELL to point to our own cmdproxy. The loop below will
2765 then disregard PATH_EXEC and the default value. */
2766 if (within_build_tree
)
2768 _snprintf (buf
, sizeof (buf
) - 1,
2769 "SHELL=%s/nt/cmdproxy.exe", modname
);
2770 _putenv (strdup (buf
));
2775 for (i
= 0; i
< N_ENV_VARS
; i
++)
2777 if (!getenv (env_vars
[i
].name
))
2780 char bufc
[SET_ENV_BUF_SIZE
];
2782 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2783 /* Also ignore empty environment variables. */
2788 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2790 /* Look for cmdproxy.exe in every directory in
2791 PATH_EXEC. FIXME: This does not find cmdproxy
2792 in nt/ when we run uninstalled. */
2793 char fname
[MAX_PATH
];
2794 const char *pstart
= PATH_EXEC
, *pend
;
2797 pend
= _mbschr (pstart
, ';');
2799 pend
= pstart
+ strlen (pstart
);
2800 /* Be defensive against series of ;;; characters. */
2803 strncpy (fname
, pstart
, pend
- pstart
);
2804 fname
[pend
- pstart
] = '/';
2805 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2806 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2808 if (sys_access (bufc
, F_OK
) == 0)
2821 /* If not found in any directory, use the
2822 default as the last resort. */
2823 lpval
= (char *)env_vars
[i
].def_value
;
2824 dwType
= REG_EXPAND_SZ
;
2830 lpval
= (char *)env_vars
[i
].def_value
;
2831 dwType
= REG_EXPAND_SZ
;
2833 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2834 Vdelayed_warnings_list
2836 (listn (CONSTYPE_HEAP
, 2,
2837 intern ("initialization"), build_string
2838 ("Use of `C:\\.emacs' without defining `HOME'\n"
2839 "in the environment is deprecated, "
2840 "see `Windows HOME' in the Emacs manual.")),
2841 Vdelayed_warnings_list
);
2846 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2848 if (dwType
== REG_EXPAND_SZ
)
2849 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2850 else if (dwType
== REG_SZ
)
2851 strcpy (buf1
, (char *)lpval
);
2852 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2854 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2856 _putenv (strdup (buf2
));
2866 /* Rebuild system configuration to reflect invoking system. */
2867 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2869 /* Another special case: on NT, the PATH variable is actually named
2870 "Path" although cmd.exe (perhaps NT itself) arranges for
2871 environment variable lookup and setting to be case insensitive.
2872 However, Emacs assumes a fully case sensitive environment, so we
2873 need to change "Path" to "PATH" to match the expectations of
2874 various elisp packages. We do this by the sneaky method of
2875 modifying the string in the C runtime environ entry.
2877 The same applies to COMSPEC. */
2880 const char *path
= "PATH=";
2881 int path_len
= strlen (path
);
2882 const char *comspec
= "COMSPEC=";
2883 int comspec_len
= strlen (comspec
);
2885 for (envp
= environ
; *envp
; envp
++)
2886 if (_strnicmp (*envp
, path
, path_len
) == 0)
2887 memcpy (*envp
, path
, path_len
);
2888 else if (_strnicmp (*envp
, comspec
, comspec_len
) == 0)
2889 memcpy (*envp
, comspec
, comspec_len
);
2891 /* Make the same modification to `process-environment' which has
2892 already been initialized in set_initial_environment. */
2893 for (Lisp_Object env
= Vprocess_environment
; CONSP (env
); env
= XCDR (env
))
2895 Lisp_Object entry
= XCAR (env
);
2896 if (_strnicmp (SDATA (entry
), path
, path_len
) == 0)
2897 for (int i
= 0; i
< path_len
; i
++)
2898 SSET (entry
, i
, path
[i
]);
2899 else if (_strnicmp (SDATA (entry
), comspec
, comspec_len
) == 0)
2900 for (int i
= 0; i
< comspec_len
; i
++)
2901 SSET (entry
, i
, comspec
[i
]);
2905 /* Remember the initial working directory for getcwd. */
2906 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2907 Does it matter anywhere in Emacs? */
2908 if (w32_unicode_filenames
)
2910 wchar_t wstartup_dir
[MAX_PATH
];
2912 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2914 filename_from_utf16 (wstartup_dir
, startup_dir
);
2918 char astartup_dir
[MAX_PATH
];
2920 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2922 filename_from_ansi (astartup_dir
, startup_dir
);
2926 static char modname
[MAX_PATH
];
2928 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2933 /* Determine if there is a middle mouse button, to allow parse_button
2934 to decide whether right mouse events should be mouse-2 or
2936 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2941 /* Called from expand-file-name when default-directory is not a string. */
2944 emacs_root_dir (void)
2946 static char root_dir
[MAX_UTF8_PATH
];
2949 p
= getenv ("emacs_dir");
2952 filename_from_ansi (p
, root_dir
);
2953 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2954 dostounix_filename (root_dir
);
2958 #include <sys/timeb.h>
2960 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2962 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2967 tv
->tv_sec
= tb
.time
;
2968 tv
->tv_usec
= tb
.millitm
* 1000L;
2969 /* Implementation note: _ftime sometimes doesn't update the dstflag
2970 according to the new timezone when the system timezone is
2971 changed. We could fix that by using GetSystemTime and
2972 GetTimeZoneInformation, but that doesn't seem necessary, since
2973 Emacs always calls gettimeofday with the 2nd argument NULL (see
2974 current_emacs_time). */
2977 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2978 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2983 /* Emulate fdutimens. */
2985 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2986 TIMESPEC[0] and TIMESPEC[1], respectively.
2987 FD must be either negative -- in which case it is ignored --
2988 or a file descriptor that is open on FILE.
2989 If FD is nonnegative, then FILE can be NULL, which means
2990 use just futimes instead of utimes.
2991 If TIMESPEC is null, FAIL.
2992 Return 0 on success, -1 (setting errno) on failure. */
2995 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
3002 if (fd
< 0 && !file
)
3007 /* _futime's prototype defines 2nd arg as having the type 'struct
3008 _utimbuf', while utime needs to accept 'struct utimbuf' for
3009 compatibility with Posix. So we need to use 2 different (but
3010 equivalent) types to avoid compiler warnings, sigh. */
3013 struct _utimbuf _ut
;
3015 _ut
.actime
= timespec
[0].tv_sec
;
3016 _ut
.modtime
= timespec
[1].tv_sec
;
3017 return _futime (fd
, &_ut
);
3023 ut
.actime
= timespec
[0].tv_sec
;
3024 ut
.modtime
= timespec
[1].tv_sec
;
3025 /* Call 'utime', which is implemented below, not the MS library
3026 function, which fails on directories. */
3027 return utime (file
, &ut
);
3032 /* ------------------------------------------------------------------------- */
3033 /* IO support and wrapper functions for the Windows API. */
3034 /* ------------------------------------------------------------------------- */
3036 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3037 on network directories, so we handle that case here.
3038 (Ulrich Leodolter, 1/11/95). */
3040 sys_ctime (const time_t *t
)
3042 char *str
= (char *) ctime (t
);
3043 return (str
? str
: (char *)"Sun Jan 01 00:00:00 1970");
3046 /* Emulate sleep...we could have done this with a define, but that
3047 would necessitate including windows.h in the files that used it.
3048 This is much easier. */
3050 sys_sleep (int seconds
)
3052 Sleep (seconds
* 1000);
3055 /* Internal MSVC functions for low-level descriptor munging */
3056 extern int __cdecl
_set_osfhnd (int fd
, long h
);
3057 extern int __cdecl
_free_osfhnd (int fd
);
3059 /* parallel array of private info on file handles */
3060 filedesc fd_info
[ MAXDESC
];
3062 typedef struct volume_info_data
{
3063 struct volume_info_data
* next
;
3065 /* time when info was obtained */
3068 /* actual volume info */
3077 /* Global referenced by various functions. */
3078 static volume_info_data volume_info
;
3080 /* Vector to indicate which drives are local and fixed (for which cached
3081 data never expires). */
3082 static BOOL fixed_drives
[26];
3084 /* Consider cached volume information to be stale if older than 10s,
3085 at least for non-local drives. Info for fixed drives is never stale. */
3086 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3087 #define VOLINFO_STILL_VALID( root_dir, info ) \
3088 ( ( isalpha (root_dir[0]) && \
3089 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3090 || GetTickCount () - info->timestamp < 10000 )
3092 /* Cache support functions. */
3094 /* Simple linked list with linear search is sufficient. */
3095 static volume_info_data
*volume_cache
= NULL
;
3097 static volume_info_data
*
3098 lookup_volume_info (char * root_dir
)
3100 volume_info_data
* info
;
3102 for (info
= volume_cache
; info
; info
= info
->next
)
3103 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
3109 add_volume_info (char * root_dir
, volume_info_data
* info
)
3111 info
->root_dir
= xstrdup (root_dir
);
3112 unixtodos_filename (info
->root_dir
);
3113 info
->next
= volume_cache
;
3114 volume_cache
= info
;
3118 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3119 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3120 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3121 static volume_info_data
*
3122 GetCachedVolumeInformation (char * root_dir
)
3124 volume_info_data
* info
;
3125 char default_root
[ MAX_UTF8_PATH
];
3126 char name
[MAX_PATH
+1];
3127 char type
[MAX_PATH
+1];
3129 /* NULL for root_dir means use root from current directory. */
3130 if (root_dir
== NULL
)
3132 if (w32_unicode_filenames
)
3134 wchar_t curdirw
[MAX_PATH
];
3136 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3138 filename_from_utf16 (curdirw
, default_root
);
3142 char curdira
[MAX_PATH
];
3144 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3146 filename_from_ansi (curdira
, default_root
);
3148 parse_root (default_root
, (const char **)&root_dir
);
3150 root_dir
= default_root
;
3153 /* Local fixed drives can be cached permanently. Removable drives
3154 cannot be cached permanently, since the volume name and serial
3155 number (if nothing else) can change. Remote drives should be
3156 treated as if they are removable, since there is no sure way to
3157 tell whether they are or not. Also, the UNC association of drive
3158 letters mapped to remote volumes can be changed at any time (even
3159 by other processes) without notice.
3161 As a compromise, so we can benefit from caching info for remote
3162 volumes, we use a simple expiry mechanism to invalidate cache
3163 entries that are more than ten seconds old. */
3166 /* No point doing this, because WNetGetConnection is even slower than
3167 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3168 GetDriveType is about the only call of this type which does not
3169 involve network access, and so is extremely quick). */
3171 /* Map drive letter to UNC if remote. */
3172 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3174 char remote_name
[ 256 ];
3175 char drive
[3] = { root_dir
[0], ':' };
3177 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3179 /* do something */ ;
3183 info
= lookup_volume_info (root_dir
);
3185 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3191 /* Info is not cached, or is stale. */
3192 if (w32_unicode_filenames
)
3194 wchar_t root_w
[MAX_PATH
];
3195 wchar_t name_w
[MAX_PATH
+1];
3196 wchar_t type_w
[MAX_PATH
+1];
3198 filename_to_utf16 (root_dir
, root_w
);
3199 if (!GetVolumeInformationW (root_w
,
3200 name_w
, sizeof (name_w
),
3204 type_w
, sizeof (type_w
)))
3206 /* Hmm... not really 100% correct, as these 2 are not file
3208 filename_from_utf16 (name_w
, name
);
3209 filename_from_utf16 (type_w
, type
);
3213 char root_a
[MAX_PATH
];
3214 char name_a
[MAX_PATH
+1];
3215 char type_a
[MAX_PATH
+1];
3217 filename_to_ansi (root_dir
, root_a
);
3218 if (!GetVolumeInformationA (root_a
,
3219 name_a
, sizeof (name_a
),
3223 type_a
, sizeof (type_a
)))
3225 filename_from_ansi (name_a
, name
);
3226 filename_from_ansi (type_a
, type
);
3229 /* Cache the volume information for future use, overwriting existing
3230 entry if present. */
3233 info
= xmalloc (sizeof (volume_info_data
));
3234 add_volume_info (root_dir
, info
);
3242 info
->name
= xstrdup (name
);
3243 unixtodos_filename (info
->name
);
3244 info
->serialnum
= serialnum
;
3245 info
->maxcomp
= maxcomp
;
3246 info
->flags
= flags
;
3247 info
->type
= xstrdup (type
);
3248 info
->timestamp
= GetTickCount ();
3254 /* Get information on the volume where NAME is held; set path pointer to
3255 start of pathname in NAME (past UNC header\volume header if present),
3256 if pPath is non-NULL.
3258 Note: if NAME includes symlinks, the information is for the volume
3259 of the symlink, not of its target. That's because, even though
3260 GetVolumeInformation returns information about the symlink target
3261 of its argument, we only pass the root directory to
3262 GetVolumeInformation, not the full NAME. */
3264 get_volume_info (const char * name
, const char ** pPath
)
3266 char temp
[MAX_UTF8_PATH
];
3267 char *rootname
= NULL
; /* default to current volume */
3268 volume_info_data
* info
;
3269 int root_len
= parse_root (name
, pPath
);
3274 /* Copy the root name of the volume, if given. */
3277 strncpy (temp
, name
, root_len
);
3278 temp
[root_len
] = '\0';
3279 unixtodos_filename (temp
);
3283 info
= GetCachedVolumeInformation (rootname
);
3286 /* Set global referenced by other functions. */
3287 volume_info
= *info
;
3293 /* Determine if volume is FAT format (ie. only supports short 8.3
3294 names); also set path pointer to start of pathname in name, if
3295 pPath is non-NULL. */
3297 is_fat_volume (const char * name
, const char ** pPath
)
3299 if (get_volume_info (name
, pPath
))
3300 return (volume_info
.maxcomp
== 12);
3304 /* Convert all slashes in a filename to backslashes, and map filename
3305 to a valid 8.3 name if necessary. The result is a pointer to a
3306 static buffer, so CAVEAT EMPTOR! */
3307 const char *map_w32_filename (const char *, const char **);
3310 map_w32_filename (const char * name
, const char ** pPath
)
3312 static char shortname
[MAX_UTF8_PATH
];
3313 char * str
= shortname
;
3316 const char * save_name
= name
;
3318 if (strlen (name
) >= sizeof (shortname
))
3320 /* Return a filename which will cause callers to fail. */
3321 strcpy (shortname
, "?");
3325 if (!fatal_error_in_progress
/* disable fancy processing during crash */
3326 && is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3328 register int left
= 8; /* maximum number of chars in part */
3329 register int extn
= 0; /* extension added? */
3330 register int dots
= 2; /* maximum number of dots allowed */
3333 *str
++ = *name
++; /* skip past UNC header */
3335 while ((c
= *name
++))
3342 *str
++ = (c
== ':' ? ':' : '\\');
3343 extn
= 0; /* reset extension flags */
3344 dots
= 2; /* max 2 dots */
3345 left
= 8; /* max length 8 for main part */
3350 /* Convert path components of the form .xxx to _xxx,
3351 but leave . and .. as they are. This allows .emacs
3352 to be read as _emacs, for example. */
3356 IS_DIRECTORY_SEP (*name
))
3371 extn
= 1; /* we've got an extension */
3372 left
= 3; /* 3 chars in extension */
3376 /* any embedded dots after the first are converted to _ */
3381 case '#': /* don't lose these, they're important */
3383 str
[-1] = c
; /* replace last character of part */
3386 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3388 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3390 dots
= 0; /* started a path component */
3399 strcpy (shortname
, name
);
3400 unixtodos_filename (shortname
);
3404 *pPath
= shortname
+ (path
- save_name
);
3410 is_exec (const char * name
)
3412 char * p
= strrchr (name
, '.');
3415 && (xstrcasecmp (p
, ".exe") == 0 ||
3416 xstrcasecmp (p
, ".com") == 0 ||
3417 xstrcasecmp (p
, ".bat") == 0 ||
3418 xstrcasecmp (p
, ".cmd") == 0));
3421 /* Emulate the Unix directory procedures opendir, closedir, and
3422 readdir. We rename them to sys_* names because some versions of
3423 MinGW startup code call opendir and readdir to glob wildcards, and
3424 the code that calls them doesn't grok UTF-8 encoded file names we
3425 produce in dirent->d_name[]. */
3427 struct dirent dir_static
; /* simulated directory contents */
3428 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3429 static int dir_is_fat
;
3430 static char dir_pathname
[MAX_UTF8_PATH
];
3431 static WIN32_FIND_DATAW dir_find_data_w
;
3432 static WIN32_FIND_DATAA dir_find_data_a
;
3433 #define DIR_FIND_DATA_W 1
3434 #define DIR_FIND_DATA_A 2
3435 static int last_dir_find_data
= -1;
3437 /* Support shares on a network resource as subdirectories of a read-only
3439 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3440 static HANDLE
open_unc_volume (const char *);
3441 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3442 static void close_unc_volume (HANDLE
);
3445 sys_opendir (const char *filename
)
3449 /* Opening is done by FindFirstFile. However, a read is inherent to
3450 this operation, so we defer the open until read time. */
3452 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3454 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3457 /* Note: We don't support traversal of UNC volumes via symlinks.
3458 Doing so would mean punishing 99.99% of use cases by resolving
3459 all the possible symlinks in FILENAME, recursively. */
3460 if (is_unc_volume (filename
))
3462 wnet_enum_handle
= open_unc_volume (filename
);
3463 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3467 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3474 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3475 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3476 /* Note: We don't support symlinks to file names on FAT volumes.
3477 Doing so would mean punishing 99.99% of use cases by resolving
3478 all the possible symlinks in FILENAME, recursively. */
3479 dir_is_fat
= is_fat_volume (filename
, NULL
);
3485 sys_closedir (DIR *dirp
)
3487 /* If we have a find-handle open, close it. */
3488 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3490 FindClose (dir_find_handle
);
3491 dir_find_handle
= INVALID_HANDLE_VALUE
;
3493 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3495 close_unc_volume (wnet_enum_handle
);
3496 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3498 xfree ((char *) dirp
);
3502 sys_readdir (DIR *dirp
)
3504 int downcase
= !NILP (Vw32_downcase_file_names
);
3506 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3508 if (!read_unc_volume (wnet_enum_handle
,
3509 dir_find_data_w
.cFileName
,
3510 dir_find_data_a
.cFileName
,
3514 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3515 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3517 char filename
[MAX_UTF8_PATH
];
3519 bool last_slash
= true;
3521 /* Note: We don't need to worry about dir_pathname being longer
3522 than MAX_UTF8_PATH, as sys_opendir already took care of that
3523 when it called map_w32_filename: that function will put a "?"
3524 in its return value in that case, thus failing all the calls
3526 strcpy (filename
, dir_pathname
);
3527 ln
= strlen (filename
);
3528 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3531 /* Note: No need to resolve symlinks in FILENAME, because
3532 FindFirst opens the directory that is the target of a
3534 if (w32_unicode_filenames
)
3536 wchar_t fnw
[MAX_PATH
+ 2];
3538 filename_to_utf16 (filename
, fnw
);
3540 wcscat (fnw
, L
"\\");
3542 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3546 char fna
[MAX_PATH
+ 2];
3548 filename_to_ansi (filename
, fna
);
3552 /* If FILENAME is not representable by the current ANSI
3553 codepage, we don't want FindFirstFileA to interpret the
3554 '?' characters as a wildcard. */
3555 if (_mbspbrk (fna
, "?"))
3556 dir_find_handle
= INVALID_HANDLE_VALUE
;
3558 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3561 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3563 /* Any changes in the value of errno here should be in sync
3564 with what directory_files_internal does when it calls
3566 switch (GetLastError ())
3568 /* Windows uses this value when FindFirstFile finds no
3569 files that match the wildcard. This is not supposed
3570 to happen, since our wildcard is "*", but just in
3571 case, if there's some weird empty directory with not
3572 even "." and ".." entries... */
3573 case ERROR_FILE_NOT_FOUND
:
3578 case ERROR_ACCESS_DENIED
:
3579 case ERROR_NETWORK_ACCESS_DENIED
:
3582 case ERROR_PATH_NOT_FOUND
:
3583 case ERROR_INVALID_DRIVE
:
3584 case ERROR_NOT_READY
:
3585 case ERROR_BAD_NETPATH
:
3586 case ERROR_BAD_NET_NAME
:
3593 else if (w32_unicode_filenames
)
3595 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3603 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3610 /* Emacs never uses this value, so don't bother making it match
3611 value returned by stat(). */
3612 dir_static
.d_ino
= 1;
3614 if (w32_unicode_filenames
)
3616 if (downcase
|| dir_is_fat
)
3618 wchar_t tem
[MAX_PATH
];
3620 wcscpy (tem
, dir_find_data_w
.cFileName
);
3622 filename_from_utf16 (tem
, dir_static
.d_name
);
3625 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3626 last_dir_find_data
= DIR_FIND_DATA_W
;
3632 /* If the file name in cFileName[] includes `?' characters, it
3633 means the original file name used characters that cannot be
3634 represented by the current ANSI codepage. To avoid total
3635 lossage, retrieve the short 8+3 alias of the long file
3637 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3639 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3640 /* 8+3 aliases are returned in all caps, which could break
3641 various alists that look at filenames' extensions. */
3644 else if (downcase
|| dir_is_fat
)
3645 strcpy (tem
, dir_find_data_a
.cFileName
);
3647 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3648 if (downcase
|| dir_is_fat
)
3651 filename_from_ansi (tem
, dir_static
.d_name
);
3653 last_dir_find_data
= DIR_FIND_DATA_A
;
3656 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3657 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3658 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3664 open_unc_volume (const char *path
)
3666 const char *fn
= map_w32_filename (path
, NULL
);
3670 if (w32_unicode_filenames
)
3673 wchar_t fnw
[MAX_PATH
];
3675 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3676 nrw
.dwType
= RESOURCETYPE_DISK
;
3677 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3678 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3679 nrw
.lpLocalName
= NULL
;
3680 filename_to_utf16 (fn
, fnw
);
3681 nrw
.lpRemoteName
= fnw
;
3682 nrw
.lpComment
= NULL
;
3683 nrw
.lpProvider
= NULL
;
3685 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3686 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3693 nra
.dwScope
= RESOURCE_GLOBALNET
;
3694 nra
.dwType
= RESOURCETYPE_DISK
;
3695 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3696 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3697 nra
.lpLocalName
= NULL
;
3698 filename_to_ansi (fn
, fna
);
3699 nra
.lpRemoteName
= fna
;
3700 nra
.lpComment
= NULL
;
3701 nra
.lpProvider
= NULL
;
3703 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3704 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3706 if (result
== NO_ERROR
)
3710 /* Make sure directory_files_internal reports a sensible error. */
3712 return INVALID_HANDLE_VALUE
;
3717 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3722 DWORD bufsize
= 512;
3726 if (w32_unicode_filenames
)
3731 buffer
= alloca (bufsize
);
3732 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3733 if (result
!= NO_ERROR
)
3735 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3736 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3738 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3740 wcsncpy (fname_w
, ptrw
, size
);
3745 int dbcs_p
= max_filename_mbslen () > 1;
3748 buffer
= alloca (bufsize
);
3749 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3750 if (result
!= NO_ERROR
)
3752 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3755 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3758 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3759 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3762 strncpy (fname_a
, ptra
, size
);
3770 close_unc_volume (HANDLE henum
)
3772 if (henum
!= INVALID_HANDLE_VALUE
)
3773 WNetCloseEnum (henum
);
3777 unc_volume_file_attributes (const char *path
)
3782 henum
= open_unc_volume (path
);
3783 if (henum
== INVALID_HANDLE_VALUE
)
3786 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3788 close_unc_volume (henum
);
3793 /* Ensure a network connection is authenticated. */
3795 logon_network_drive (const char *path
)
3797 char share
[MAX_UTF8_PATH
];
3804 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3805 drvtype
= DRIVE_REMOTE
;
3806 else if (path
[0] == '\0' || path
[1] != ':')
3807 drvtype
= GetDriveType (NULL
);
3814 drvtype
= GetDriveType (drive
);
3817 /* Only logon to networked drives. */
3818 if (drvtype
!= DRIVE_REMOTE
)
3822 strncpy (share
, path
, MAX_UTF8_PATH
);
3823 /* Truncate to just server and share name. */
3824 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3826 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3833 if (w32_unicode_filenames
)
3835 NETRESOURCEW resourcew
;
3836 wchar_t share_w
[MAX_PATH
];
3838 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3839 resourcew
.dwType
= RESOURCETYPE_DISK
;
3840 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3841 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3842 resourcew
.lpLocalName
= NULL
;
3843 filename_to_utf16 (share
, share_w
);
3844 resourcew
.lpRemoteName
= share_w
;
3845 resourcew
.lpProvider
= NULL
;
3847 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3851 NETRESOURCEA resourcea
;
3852 char share_a
[MAX_PATH
];
3854 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3855 resourcea
.dwType
= RESOURCETYPE_DISK
;
3856 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3857 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3858 resourcea
.lpLocalName
= NULL
;
3859 filename_to_ansi (share
, share_a
);
3860 resourcea
.lpRemoteName
= share_a
;
3861 resourcea
.lpProvider
= NULL
;
3863 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3869 case ERROR_ALREADY_ASSIGNED
:
3871 case ERROR_ACCESS_DENIED
:
3872 case ERROR_LOGON_FAILURE
:
3878 case ERROR_BAD_NET_NAME
:
3879 case ERROR_NO_NET_OR_BAD_PATH
:
3880 case ERROR_NO_NETWORK
:
3881 case ERROR_CANCELLED
:
3888 /* Emulate faccessat(2). */
3890 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3894 if (dirfd
!= AT_FDCWD
3895 && !(IS_DIRECTORY_SEP (path
[0])
3896 || IS_DEVICE_SEP (path
[1])))
3902 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3903 newer versions blow up when passed D_OK. */
3904 path
= map_w32_filename (path
, NULL
);
3905 /* If the last element of PATH is a symlink, we need to resolve it
3906 to get the attributes of its target file. Note: any symlinks in
3907 PATH elements other than the last one are transparently resolved
3908 by GetFileAttributes below. */
3909 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3910 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3911 path
= chase_symlinks (path
);
3913 if (w32_unicode_filenames
)
3915 wchar_t path_w
[MAX_PATH
];
3917 filename_to_utf16 (path
, path_w
);
3918 attributes
= GetFileAttributesW (path_w
);
3922 char path_a
[MAX_PATH
];
3924 filename_to_ansi (path
, path_a
);
3925 attributes
= GetFileAttributesA (path_a
);
3928 if (attributes
== -1)
3930 DWORD w32err
= GetLastError ();
3934 case ERROR_INVALID_NAME
:
3935 case ERROR_BAD_PATHNAME
:
3936 if (is_unc_volume (path
))
3938 attributes
= unc_volume_file_attributes (path
);
3939 if (attributes
== -1)
3947 case ERROR_FILE_NOT_FOUND
:
3948 case ERROR_BAD_NETPATH
:
3959 if ((mode
& X_OK
) != 0
3960 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3965 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3970 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3978 /* A special test for DIRNAME being a directory accessible by the
3979 current user. This is needed because the security permissions in
3980 directory's ACLs are not visible in the Posix-style mode bits
3981 returned by 'stat' and in attributes returned by GetFileAttributes.
3982 So a directory would seem like it's readable by the current user,
3983 but will in fact error out with EACCES when they actually try. */
3985 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
3987 char pattern
[MAX_UTF8_PATH
];
3988 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
3991 /* Network volumes need a different reading method. */
3992 if (is_unc_volume (dirname
))
3994 void *read_result
= NULL
;
3995 wchar_t fnw
[MAX_PATH
];
3998 dh
= open_unc_volume (dirname
);
3999 if (dh
!= INVALID_HANDLE_VALUE
)
4001 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
4002 close_unc_volume (dh
);
4004 /* Treat empty volumes as accessible. */
4005 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
4008 /* Note: map_w32_filename makes sure DIRNAME is not longer than
4010 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
4012 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
4013 opens the directory that is the target of a symlink. */
4014 if (w32_unicode_filenames
)
4016 wchar_t pat_w
[MAX_PATH
+ 2];
4017 WIN32_FIND_DATAW dfd_w
;
4019 filename_to_utf16 (pattern
, pat_w
);
4021 wcscat (pat_w
, L
"\\");
4022 wcscat (pat_w
, L
"*");
4023 dh
= FindFirstFileW (pat_w
, &dfd_w
);
4027 char pat_a
[MAX_PATH
+ 2];
4028 WIN32_FIND_DATAA dfd_a
;
4030 filename_to_ansi (pattern
, pat_a
);
4032 strcpy (pat_a
, "\\");
4033 strcat (pat_a
, "*");
4034 /* In case DIRNAME cannot be expressed in characters from the
4035 current ANSI codepage. */
4036 if (_mbspbrk (pat_a
, "?"))
4037 dh
= INVALID_HANDLE_VALUE
;
4039 dh
= FindFirstFileA (pat_a
, &dfd_a
);
4042 if (dh
== INVALID_HANDLE_VALUE
)
4048 /* A version of 'access' to be used locally with file names in
4049 locale-specific encoding. Does not resolve symlinks and does not
4050 support file names on FAT12 and FAT16 volumes, but that's OK, since
4051 we only invoke this function for files inside the Emacs source or
4052 installation tree, on directories (so any symlinks should have the
4053 directory bit set), and on short file names such as "C:/.emacs". */
4055 sys_access (const char *fname
, int mode
)
4057 char fname_copy
[MAX_PATH
], *p
;
4060 strcpy (fname_copy
, fname
);
4061 /* Do the equivalent of unixtodos_filename. */
4062 for (p
= fname_copy
; *p
; p
= CharNext (p
))
4066 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
4068 DWORD w32err
= GetLastError ();
4072 case ERROR_INVALID_NAME
:
4073 case ERROR_BAD_PATHNAME
:
4074 case ERROR_FILE_NOT_FOUND
:
4075 case ERROR_BAD_NETPATH
:
4084 if ((mode
& X_OK
) != 0
4085 && !(is_exec (fname_copy
)
4086 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4091 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4096 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4104 /* Shadow some MSVC runtime functions to map requests for long filenames
4105 to reasonable short names if necessary. This was originally added to
4106 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4110 sys_chdir (const char * path
)
4112 path
= map_w32_filename (path
, NULL
);
4113 if (w32_unicode_filenames
)
4115 wchar_t newdir_w
[MAX_PATH
];
4117 if (filename_to_utf16 (path
, newdir_w
) == 0)
4118 return _wchdir (newdir_w
);
4123 char newdir_a
[MAX_PATH
];
4125 if (filename_to_ansi (path
, newdir_a
) == 0)
4126 return _chdir (newdir_a
);
4132 sys_chmod (const char * path
, int mode
)
4134 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4135 if (w32_unicode_filenames
)
4137 wchar_t path_w
[MAX_PATH
];
4139 filename_to_utf16 (path
, path_w
);
4140 return _wchmod (path_w
, mode
);
4144 char path_a
[MAX_PATH
];
4146 filename_to_ansi (path
, path_a
);
4147 return _chmod (path_a
, mode
);
4152 sys_creat (const char * path
, int mode
)
4154 path
= map_w32_filename (path
, NULL
);
4155 if (w32_unicode_filenames
)
4157 wchar_t path_w
[MAX_PATH
];
4159 filename_to_utf16 (path
, path_w
);
4160 return _wcreat (path_w
, mode
);
4164 char path_a
[MAX_PATH
];
4166 filename_to_ansi (path
, path_a
);
4167 return _creat (path_a
, mode
);
4172 sys_fopen (const char * path
, const char * mode
)
4176 const char * mode_save
= mode
;
4178 /* Force all file handles to be non-inheritable. This is necessary to
4179 ensure child processes don't unwittingly inherit handles that might
4180 prevent future file access. */
4184 else if (mode
[0] == 'w' || mode
[0] == 'a')
4185 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4189 /* Only do simplistic option parsing. */
4193 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4196 else if (mode
[0] == 'b')
4201 else if (mode
[0] == 't')
4208 path
= map_w32_filename (path
, NULL
);
4209 if (w32_unicode_filenames
)
4211 wchar_t path_w
[MAX_PATH
];
4213 filename_to_utf16 (path
, path_w
);
4214 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4218 char path_a
[MAX_PATH
];
4220 filename_to_ansi (path
, path_a
);
4221 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4226 return _fdopen (fd
, mode_save
);
4229 /* This only works on NTFS volumes, but is useful to have. */
4231 sys_link (const char * old
, const char * new)
4235 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4236 wchar_t oldname_w
[MAX_PATH
];
4237 char oldname_a
[MAX_PATH
];
4239 if (old
== NULL
|| new == NULL
)
4245 strcpy (oldname
, map_w32_filename (old
, NULL
));
4246 strcpy (newname
, map_w32_filename (new, NULL
));
4248 if (w32_unicode_filenames
)
4250 filename_to_utf16 (oldname
, oldname_w
);
4251 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4252 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4256 filename_to_ansi (oldname
, oldname_a
);
4257 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4258 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4260 if (fileh
!= INVALID_HANDLE_VALUE
)
4264 /* Confusingly, the "alternate" stream name field does not apply
4265 when restoring a hard link, and instead contains the actual
4266 stream data for the link (ie. the name of the link to create).
4267 The WIN32_STREAM_ID structure before the cStreamName field is
4268 the stream header, which is then immediately followed by the
4272 WIN32_STREAM_ID wid
;
4273 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4276 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4277 indicates that flag is unsupported for CP_UTF8, and OTOH says
4278 it is the default anyway. */
4279 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4280 data
.wid
.cStreamName
, MAX_PATH
);
4283 LPVOID context
= NULL
;
4286 data
.wid
.dwStreamId
= BACKUP_LINK
;
4287 data
.wid
.dwStreamAttributes
= 0;
4288 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4289 data
.wid
.Size
.HighPart
= 0;
4290 data
.wid
.dwStreamNameSize
= 0;
4292 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4293 offsetof (WIN32_STREAM_ID
, cStreamName
)
4294 + data
.wid
.Size
.LowPart
,
4295 &wbytes
, FALSE
, FALSE
, &context
)
4296 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4303 DWORD err
= GetLastError ();
4308 case ERROR_ACCESS_DENIED
:
4309 /* This is what happens when OLDNAME is a directory,
4310 since Windows doesn't support hard links to
4311 directories. Posix says to set errno to EPERM in
4313 if (w32_unicode_filenames
)
4314 attributes
= GetFileAttributesW (oldname_w
);
4316 attributes
= GetFileAttributesA (oldname_a
);
4317 if (attributes
!= -1
4318 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4320 else if (attributes
== -1
4321 && is_unc_volume (oldname
)
4322 && unc_volume_file_attributes (oldname
) != -1)
4327 case ERROR_TOO_MANY_LINKS
:
4330 case ERROR_NOT_SAME_DEVICE
:
4340 CloseHandle (fileh
);
4349 sys_mkdir (const char * path
)
4351 path
= map_w32_filename (path
, NULL
);
4353 if (w32_unicode_filenames
)
4355 wchar_t path_w
[MAX_PATH
];
4357 filename_to_utf16 (path
, path_w
);
4358 return _wmkdir (path_w
);
4362 char path_a
[MAX_PATH
];
4364 filename_to_ansi (path
, path_a
);
4365 return _mkdir (path_a
);
4370 sys_open (const char * path
, int oflag
, int mode
)
4372 const char* mpath
= map_w32_filename (path
, NULL
);
4375 if (w32_unicode_filenames
)
4377 wchar_t mpath_w
[MAX_PATH
];
4379 filename_to_utf16 (mpath
, mpath_w
);
4380 /* If possible, try to open file without _O_CREAT, to be able to
4381 write to existing hidden and system files. Force all file
4382 handles to be non-inheritable. */
4383 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4384 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4386 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4390 char mpath_a
[MAX_PATH
];
4392 filename_to_ansi (mpath
, mpath_a
);
4393 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4394 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4396 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4402 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4405 Standard algorithm for generating a temporary file name seems to be
4406 use pid or tid with a letter on the front (in place of the 6 X's)
4407 and cycle through the letters to find a unique name. We extend
4408 that to allow any reasonable character as the first of the 6 X's,
4409 so that the number of simultaneously used temporary files will be
4413 mkostemp (char * template, int flags
)
4417 unsigned uid
= GetCurrentThreadId ();
4418 int save_errno
= errno
;
4419 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4422 if (template == NULL
)
4425 p
= template + strlen (template);
4427 /* replace up to the last 5 X's with uid in decimal */
4428 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4430 p
[0] = '0' + uid
% 10;
4434 if (i
< 0 && p
[0] == 'X')
4439 p
[0] = first_char
[i
];
4440 if ((fd
= sys_open (template,
4441 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4442 S_IRUSR
| S_IWUSR
)) >= 0
4450 while (++i
< sizeof (first_char
));
4453 /* Template is badly formed or else we can't generate a unique name. */
4458 fchmod (int fd
, mode_t mode
)
4464 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4467 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4470 bool have_temp_a
= false;
4472 /* MoveFile on Windows 95 doesn't correctly change the short file name
4473 alias in a number of circumstances (it is not easy to predict when
4474 just by looking at oldname and newname, unfortunately). In these
4475 cases, renaming through a temporary name avoids the problem.
4477 A second problem on Windows 95 is that renaming through a temp name when
4478 newname is uppercase fails (the final long name ends up in
4479 lowercase, although the short alias might be uppercase) UNLESS the
4480 long temp name is not 8.3.
4482 So, on Windows 95 we always rename through a temp name, and we make sure
4483 the temp name has a long extension to ensure correct renaming. */
4485 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4487 /* volume_info is set indirectly by map_w32_filename. */
4488 oldname_dev
= volume_info
.serialnum
;
4490 if (os_subtype
== OS_9X
)
4495 char oldname_a
[MAX_PATH
];
4497 oldname
= map_w32_filename (oldname
, NULL
);
4498 filename_to_ansi (oldname
, oldname_a
);
4499 filename_to_ansi (temp
, temp_a
);
4500 if ((o
= strrchr (oldname_a
, '\\')))
4503 o
= (char *) oldname_a
;
4505 if ((p
= strrchr (temp_a
, '\\')))
4512 /* Force temp name to require a manufactured 8.3 alias - this
4513 seems to make the second rename work properly. */
4514 sprintf (p
, "_.%s.%d", o
, i
);
4516 result
= rename (oldname_a
, temp_a
);
4518 /* This loop must surely terminate! */
4519 while (result
< 0 && errno
== EEXIST
);
4525 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4526 (at least if it is a file; don't do this for directories).
4528 Since we mustn't do this if we are just changing the case of the
4529 file name (we would end up deleting the file we are trying to
4530 rename!), we let rename detect if the destination file already
4531 exists - that way we avoid the possible pitfalls of trying to
4532 determine ourselves whether two names really refer to the same
4533 file, which is not always possible in the general case. (Consider
4534 all the permutations of shared or subst'd drives, etc.) */
4536 newname
= map_w32_filename (newname
, NULL
);
4538 /* volume_info is set indirectly by map_w32_filename. */
4539 newname_dev
= volume_info
.serialnum
;
4541 if (w32_unicode_filenames
)
4543 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4545 filename_to_utf16 (temp
, temp_w
);
4546 filename_to_utf16 (newname
, newname_w
);
4547 result
= _wrename (temp_w
, newname_w
);
4548 if (result
< 0 && force
)
4550 DWORD w32err
= GetLastError ();
4553 && newname_dev
!= oldname_dev
)
4555 /* The implementation of `rename' on Windows does not return
4556 errno = EXDEV when you are moving a directory to a
4557 different storage device (ex. logical disk). It returns
4558 EACCES instead. So here we handle such situations and
4562 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4563 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4566 else if (errno
== EEXIST
)
4568 if (_wchmod (newname_w
, 0666) != 0)
4570 if (_wunlink (newname_w
) != 0)
4572 result
= _wrename (temp_w
, newname_w
);
4574 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4575 && is_symlink (temp
))
4577 /* This is Windows prohibiting the user from creating a
4578 symlink in another place, since that requires
4586 char newname_a
[MAX_PATH
];
4589 filename_to_ansi (temp
, temp_a
);
4590 filename_to_ansi (newname
, newname_a
);
4591 result
= rename (temp_a
, newname_a
);
4592 if (result
< 0 && force
)
4594 DWORD w32err
= GetLastError ();
4597 && newname_dev
!= oldname_dev
)
4601 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4602 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4605 else if (errno
== EEXIST
)
4607 if (_chmod (newname_a
, 0666) != 0)
4609 if (_unlink (newname_a
) != 0)
4611 result
= rename (temp_a
, newname_a
);
4613 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4614 && is_symlink (temp
))
4623 sys_rename (char const *old
, char const *new)
4625 return sys_rename_replace (old
, new, TRUE
);
4629 sys_rmdir (const char * path
)
4631 path
= map_w32_filename (path
, NULL
);
4633 if (w32_unicode_filenames
)
4635 wchar_t path_w
[MAX_PATH
];
4637 filename_to_utf16 (path
, path_w
);
4638 return _wrmdir (path_w
);
4642 char path_a
[MAX_PATH
];
4644 filename_to_ansi (path
, path_a
);
4645 return _rmdir (path_a
);
4650 sys_unlink (const char * path
)
4654 path
= map_w32_filename (path
, NULL
);
4656 if (w32_unicode_filenames
)
4658 wchar_t path_w
[MAX_PATH
];
4660 filename_to_utf16 (path
, path_w
);
4661 /* On Unix, unlink works without write permission. */
4662 _wchmod (path_w
, 0666);
4663 rmstatus
= _wunlink (path_w
);
4665 /* Symlinks to directories can only be deleted by _rmdir;
4666 _unlink returns EACCES. */
4669 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4670 rmstatus
= _wrmdir (path_w
);
4676 char path_a
[MAX_PATH
];
4678 filename_to_ansi (path
, path_a
);
4679 _chmod (path_a
, 0666);
4680 rmstatus
= _unlink (path_a
);
4684 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4685 rmstatus
= _rmdir (path_a
);
4693 static FILETIME utc_base_ft
;
4694 static ULONGLONG utc_base
; /* In 100ns units */
4695 static int init
= 0;
4697 #define FILETIME_TO_U64(result, ft) \
4699 ULARGE_INTEGER uiTemp; \
4700 uiTemp.LowPart = (ft).dwLowDateTime; \
4701 uiTemp.HighPart = (ft).dwHighDateTime; \
4702 result = uiTemp.QuadPart; \
4706 initialize_utc_base (void)
4708 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4717 st
.wMilliseconds
= 0;
4719 SystemTimeToFileTime (&st
, &utc_base_ft
);
4720 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4724 convert_time (FILETIME ft
)
4730 initialize_utc_base ();
4734 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4737 FILETIME_TO_U64 (tmp
, ft
);
4738 return (time_t) ((tmp
- utc_base
) / 10000000L);
4742 convert_from_time_t (time_t time
, FILETIME
* pft
)
4748 initialize_utc_base ();
4752 /* time in 100ns units since 1-Jan-1601 */
4753 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4754 pft
->dwHighDateTime
= tmp
.HighPart
;
4755 pft
->dwLowDateTime
= tmp
.LowPart
;
4758 static PSECURITY_DESCRIPTOR
4759 get_file_security_desc_by_handle (HANDLE h
)
4761 PSECURITY_DESCRIPTOR psd
= NULL
;
4763 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4764 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4766 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4767 NULL
, NULL
, NULL
, NULL
, &psd
);
4768 if (err
!= ERROR_SUCCESS
)
4774 static PSECURITY_DESCRIPTOR
4775 get_file_security_desc_by_name (const char *fname
)
4777 PSECURITY_DESCRIPTOR psd
= NULL
;
4779 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4780 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4782 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4784 err
= GetLastError ();
4785 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4789 psd
= xmalloc (sd_len
);
4790 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4802 unsigned n_subauthorities
;
4804 /* Use the last sub-authority value of the RID, the relative
4805 portion of the SID, as user/group ID. */
4806 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4807 if (n_subauthorities
< 1)
4808 return 0; /* the "World" RID */
4809 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4812 /* Caching SID and account values for faster lokup. */
4816 struct w32_id
*next
;
4818 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4821 static struct w32_id
*w32_idlist
;
4824 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4826 struct w32_id
*tail
, *found
;
4828 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4830 if (equal_sid ((PSID
)tail
->sid
, sid
))
4839 strcpy (name
, found
->name
);
4847 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4850 struct w32_id
*new_entry
;
4852 /* We don't want to leave behind stale cache from when Emacs was
4856 sid_len
= get_length_sid (sid
);
4857 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4860 new_entry
->rid
= id
;
4861 strcpy (new_entry
->name
, name
);
4862 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4863 new_entry
->next
= w32_idlist
;
4864 w32_idlist
= new_entry
;
4873 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4877 SID_NAME_USE ignore
;
4879 DWORD name_len
= sizeof (name
);
4881 DWORD domain_len
= sizeof (domain
);
4886 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4887 else if (what
== GID
)
4888 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4892 if (!result
|| !is_valid_sid (sid
))
4894 else if (!w32_cached_id (sid
, id
, nm
))
4896 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4897 domain
, &domain_len
, &ignore
)
4898 || name_len
> UNLEN
+1)
4902 *id
= get_rid (sid
);
4904 w32_add_to_cache (sid
, *id
, name
);
4911 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4913 int dflt_usr
= 0, dflt_grp
= 0;
4922 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4924 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4927 /* Consider files to belong to current user/group, if we cannot get
4928 more accurate information. */
4931 st
->st_uid
= dflt_passwd
.pw_uid
;
4932 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4936 st
->st_gid
= dflt_passwd
.pw_gid
;
4937 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4941 /* Return non-zero if NAME is a potentially slow filesystem. */
4942 int is_slow_fs (const char *);
4945 is_slow_fs (const char *name
)
4950 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4951 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4952 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4953 devtype
= GetDriveType (NULL
); /* use root of current drive */
4956 /* GetDriveType needs the root directory of the drive. */
4957 strncpy (drive_root
, name
, 2);
4958 drive_root
[2] = '\\';
4959 drive_root
[3] = '\0';
4960 devtype
= GetDriveType (drive_root
);
4962 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4965 /* If this is non-zero, the caller wants accurate information about
4966 file's owner and group, which could be expensive to get. dired.c
4967 uses this flag when needed for the job at hand. */
4968 int w32_stat_get_owner_group
;
4970 /* MSVC stat function can't cope with UNC names and has other bugs, so
4971 replace it with our own. This also allows us to calculate consistent
4972 inode values and owner/group without hacks in the main Emacs code,
4973 and support file names encoded in UTF-8. */
4976 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4978 char *name
, *save_name
, *r
;
4979 WIN32_FIND_DATAW wfd_w
;
4980 WIN32_FIND_DATAA wfd_a
;
4982 unsigned __int64 fake_inode
= 0;
4985 int rootdir
= FALSE
;
4986 PSECURITY_DESCRIPTOR psd
= NULL
;
4987 int is_a_symlink
= 0;
4988 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4989 DWORD access_rights
= 0;
4990 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4991 FILETIME ctime
, atime
, wtime
;
4992 wchar_t name_w
[MAX_PATH
];
4993 char name_a
[MAX_PATH
];
4995 if (path
== NULL
|| buf
== NULL
)
5001 save_name
= name
= (char *) map_w32_filename (path
, &path
);
5002 /* Must be valid filename, no wild cards or other invalid
5004 if (strpbrk (name
, "*?|<>\""))
5010 len
= strlen (name
);
5011 /* Allocate 1 extra byte so that we could append a slash to a root
5012 directory, down below. */
5013 name
= strcpy (alloca (len
+ 2), name
);
5015 /* Avoid a somewhat costly call to is_symlink if the filesystem
5016 doesn't support symlinks. */
5017 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5018 is_a_symlink
= is_symlink (name
);
5020 /* Plan A: Open the file and get all the necessary information via
5021 the resulting handle. This solves several issues in one blow:
5023 . retrieves attributes for the target of a symlink, if needed
5024 . gets attributes of root directories and symlinks pointing to
5025 root directories, thus avoiding the need for special-casing
5026 these and detecting them by examining the file-name format
5027 . retrieves more accurate attributes (e.g., non-zero size for
5028 some directories, esp. directories that are junction points)
5029 . correctly resolves "c:/..", "/.." and similar file names
5030 . avoids run-time penalties for 99% of use cases
5032 Plan A is always tried first, unless the user asked not to (but
5033 if the file is a symlink and we need to follow links, we try Plan
5034 A even if the user asked not to).
5036 If Plan A fails, we go to Plan B (below), where various
5037 potentially expensive techniques must be used to handle "special"
5038 files such as UNC volumes etc. */
5039 if (!(NILP (Vw32_get_true_file_attributes
)
5040 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
5041 /* Following symlinks requires getting the info by handle. */
5042 || (is_a_symlink
&& follow_symlinks
))
5044 BY_HANDLE_FILE_INFORMATION info
;
5046 if (is_a_symlink
&& !follow_symlinks
)
5047 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
5048 /* READ_CONTROL access rights are required to get security info
5049 by handle. But if the OS doesn't support security in the
5050 first place, we don't need to try. */
5051 if (is_windows_9x () != TRUE
)
5052 access_rights
|= READ_CONTROL
;
5054 if (w32_unicode_filenames
)
5056 filename_to_utf16 (name
, name_w
);
5057 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5059 /* If CreateFile fails with READ_CONTROL, try again with
5060 zero as access rights. */
5061 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5062 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
5067 filename_to_ansi (name
, name_a
);
5068 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5070 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5071 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
5074 if (fh
== INVALID_HANDLE_VALUE
)
5075 goto no_true_file_attributes
;
5077 /* This is more accurate in terms of getting the correct number
5078 of links, but is quite slow (it is noticeable when Emacs is
5079 making a list of file name completions). */
5080 if (GetFileInformationByHandle (fh
, &info
))
5082 nlinks
= info
.nNumberOfLinks
;
5083 /* Might as well use file index to fake inode values, but this
5084 is not guaranteed to be unique unless we keep a handle open
5085 all the time (even then there are situations where it is
5086 not unique). Reputedly, there are at most 48 bits of info
5087 (on NTFS, presumably less on FAT). */
5088 fake_inode
= info
.nFileIndexHigh
;
5090 fake_inode
+= info
.nFileIndexLow
;
5091 serialnum
= info
.dwVolumeSerialNumber
;
5092 fs_high
= info
.nFileSizeHigh
;
5093 fs_low
= info
.nFileSizeLow
;
5094 ctime
= info
.ftCreationTime
;
5095 atime
= info
.ftLastAccessTime
;
5096 wtime
= info
.ftLastWriteTime
;
5097 fattrs
= info
.dwFileAttributes
;
5101 /* We don't go to Plan B here, because it's not clear that
5102 it's a good idea. The only known use case where
5103 CreateFile succeeds, but GetFileInformationByHandle fails
5104 (with ERROR_INVALID_FUNCTION) is for character devices
5105 such as NUL, PRN, etc. For these, switching to Plan B is
5106 a net loss, because we lose the character device
5107 attribute returned by GetFileType below (FindFirstFile
5108 doesn't set that bit in the attributes), and the other
5109 fields don't make sense for character devices anyway.
5110 Emacs doesn't really care for non-file entities in the
5111 context of l?stat, so neither do we. */
5113 /* w32err is assigned so one could put a breakpoint here and
5114 examine its value, when GetFileInformationByHandle
5116 DWORD w32err
= GetLastError ();
5120 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5126 /* Test for a symlink before testing for a directory, since
5127 symlinks to directories have the directory bit set, but we
5128 don't want them to appear as directories. */
5129 if (is_a_symlink
&& !follow_symlinks
)
5130 buf
->st_mode
= S_IFLNK
;
5131 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5132 buf
->st_mode
= S_IFDIR
;
5135 DWORD ftype
= GetFileType (fh
);
5139 case FILE_TYPE_DISK
:
5140 buf
->st_mode
= S_IFREG
;
5142 case FILE_TYPE_PIPE
:
5143 buf
->st_mode
= S_IFIFO
;
5145 case FILE_TYPE_CHAR
:
5146 case FILE_TYPE_UNKNOWN
:
5148 buf
->st_mode
= S_IFCHR
;
5151 /* We produce the fallback owner and group data, based on the
5152 current user that runs Emacs, in the following cases:
5154 . caller didn't request owner and group info
5155 . this is Windows 9X
5156 . getting security by handle failed, and we need to produce
5157 information for the target of a symlink (this is better
5158 than producing a potentially misleading info about the
5161 If getting security by handle fails, and we don't need to
5162 resolve symlinks, we try getting security by name. */
5163 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5164 get_file_owner_and_group (NULL
, buf
);
5167 psd
= get_file_security_desc_by_handle (fh
);
5170 get_file_owner_and_group (psd
, buf
);
5173 else if (!(is_a_symlink
&& follow_symlinks
))
5175 psd
= get_file_security_desc_by_name (name
);
5176 get_file_owner_and_group (psd
, buf
);
5180 get_file_owner_and_group (NULL
, buf
);
5186 no_true_file_attributes
:
5187 /* Plan B: Either getting a handle on the file failed, or the
5188 caller explicitly asked us to not bother making this
5189 information more accurate.
5191 Implementation note: In Plan B, we never bother to resolve
5192 symlinks, even if we got here because we tried Plan A and
5193 failed. That's because, even if the caller asked for extra
5194 precision by setting Vw32_get_true_file_attributes to t,
5195 resolving symlinks requires acquiring a file handle to the
5196 symlink, which we already know will fail. And if the user
5197 did not ask for extra precision, resolving symlinks will fly
5198 in the face of that request, since the user then wants the
5199 lightweight version of the code. */
5200 rootdir
= (path
>= save_name
+ len
- 1
5201 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5203 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5204 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5205 if (IS_DIRECTORY_SEP (r
[0])
5206 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5209 /* Note: If NAME is a symlink to the root of a UNC volume
5210 (i.e. "\\SERVER"), we will not detect that here, and we will
5211 return data about the symlink as result of FindFirst below.
5212 This is unfortunate, but that marginal use case does not
5213 justify a call to chase_symlinks which would impose a penalty
5214 on all the other use cases. (We get here for symlinks to
5215 roots of UNC volumes because CreateFile above fails for them,
5216 unlike with symlinks to root directories X:\ of drives.) */
5217 if (is_unc_volume (name
))
5219 fattrs
= unc_volume_file_attributes (name
);
5223 ctime
= atime
= wtime
= utc_base_ft
;
5227 /* Make sure root directories end in a slash. */
5228 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5229 strcpy (name
+ len
, "\\");
5230 if (GetDriveType (name
) < 2)
5236 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5237 ctime
= atime
= wtime
= utc_base_ft
;
5243 /* Make sure non-root directories do NOT end in a slash,
5244 otherwise FindFirstFile might fail. */
5245 if (IS_DIRECTORY_SEP (name
[len
-1]))
5248 /* (This is hacky, but helps when doing file completions on
5249 network drives.) Optimize by using information available from
5250 active readdir if possible. */
5251 len
= strlen (dir_pathname
);
5252 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5254 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5255 && last_dir_find_data
!= -1
5256 && !(is_a_symlink
&& follow_symlinks
)
5257 /* The 2 file-name comparisons below support only ASCII
5258 characters, and will lose (compare not equal) when
5259 the file names include non-ASCII characters that are
5260 the same but for the case. However, doing this
5261 properly involves: (a) converting both file names to
5262 UTF-16, (b) lower-casing both names using CharLowerW,
5263 and (c) comparing the results; this would be quite a
5264 bit slower, whereas Plan B is for users who want
5265 lightweight albeit inaccurate version of 'stat'. */
5266 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5267 && IS_DIRECTORY_SEP (name
[len
])
5268 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5270 have_wfd
= last_dir_find_data
;
5271 /* This was the last entry returned by readdir. */
5272 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5273 wfd_w
= dir_find_data_w
;
5275 wfd_a
= dir_find_data_a
;
5279 logon_network_drive (name
);
5281 if (w32_unicode_filenames
)
5283 filename_to_utf16 (name
, name_w
);
5284 fh
= FindFirstFileW (name_w
, &wfd_w
);
5285 have_wfd
= DIR_FIND_DATA_W
;
5289 filename_to_ansi (name
, name_a
);
5290 /* If NAME includes characters not representable by
5291 the current ANSI codepage, filename_to_ansi
5292 usually replaces them with a '?'. We don't want
5293 to let FindFirstFileA interpret those as wildcards,
5294 and "succeed", returning us data from some random
5295 file in the same directory. */
5296 if (_mbspbrk (name_a
, "?"))
5297 fh
= INVALID_HANDLE_VALUE
;
5299 fh
= FindFirstFileA (name_a
, &wfd_a
);
5300 have_wfd
= DIR_FIND_DATA_A
;
5302 if (fh
== INVALID_HANDLE_VALUE
)
5309 /* Note: if NAME is a symlink, the information we get from
5310 FindFirstFile is for the symlink, not its target. */
5311 if (have_wfd
== DIR_FIND_DATA_W
)
5313 fattrs
= wfd_w
.dwFileAttributes
;
5314 ctime
= wfd_w
.ftCreationTime
;
5315 atime
= wfd_w
.ftLastAccessTime
;
5316 wtime
= wfd_w
.ftLastWriteTime
;
5317 fs_high
= wfd_w
.nFileSizeHigh
;
5318 fs_low
= wfd_w
.nFileSizeLow
;
5322 fattrs
= wfd_a
.dwFileAttributes
;
5323 ctime
= wfd_a
.ftCreationTime
;
5324 atime
= wfd_a
.ftLastAccessTime
;
5325 wtime
= wfd_a
.ftLastWriteTime
;
5326 fs_high
= wfd_a
.nFileSizeHigh
;
5327 fs_low
= wfd_a
.nFileSizeLow
;
5331 serialnum
= volume_info
.serialnum
;
5333 if (is_a_symlink
&& !follow_symlinks
)
5334 buf
->st_mode
= S_IFLNK
;
5335 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5336 buf
->st_mode
= S_IFDIR
;
5338 buf
->st_mode
= S_IFREG
;
5340 get_file_owner_and_group (NULL
, buf
);
5343 buf
->st_ino
= fake_inode
;
5345 buf
->st_dev
= serialnum
;
5346 buf
->st_rdev
= serialnum
;
5348 buf
->st_size
= fs_high
;
5349 buf
->st_size
<<= 32;
5350 buf
->st_size
+= fs_low
;
5351 buf
->st_nlink
= nlinks
;
5353 /* Convert timestamps to Unix format. */
5354 buf
->st_mtime
= convert_time (wtime
);
5355 buf
->st_atime
= convert_time (atime
);
5356 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5357 buf
->st_ctime
= convert_time (ctime
);
5358 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5360 /* determine rwx permissions */
5361 if (is_a_symlink
&& !follow_symlinks
)
5362 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5365 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5366 permission
= S_IREAD
;
5368 permission
= S_IREAD
| S_IWRITE
;
5370 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5371 permission
|= S_IEXEC
;
5372 else if (is_exec (name
))
5373 permission
|= S_IEXEC
;
5376 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5382 stat (const char * path
, struct stat
* buf
)
5384 return stat_worker (path
, buf
, 1);
5388 lstat (const char * path
, struct stat
* buf
)
5390 return stat_worker (path
, buf
, 0);
5394 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5396 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5397 This is good enough for the current usage in Emacs, but is fragile.
5399 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5400 Gnulib does this and can serve as a model. */
5401 char fullname
[MAX_UTF8_PATH
];
5405 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5407 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5408 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5411 errno
= ENAMETOOLONG
;
5417 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5420 /* Provide fstat and utime as well as stat for consistent handling of
5423 fstat (int desc
, struct stat
* buf
)
5425 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5426 BY_HANDLE_FILE_INFORMATION info
;
5427 unsigned __int64 fake_inode
;
5430 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5432 case FILE_TYPE_DISK
:
5433 buf
->st_mode
= S_IFREG
;
5434 if (!GetFileInformationByHandle (fh
, &info
))
5440 case FILE_TYPE_PIPE
:
5441 buf
->st_mode
= S_IFIFO
;
5443 case FILE_TYPE_CHAR
:
5444 case FILE_TYPE_UNKNOWN
:
5446 buf
->st_mode
= S_IFCHR
;
5448 memset (&info
, 0, sizeof (info
));
5449 info
.dwFileAttributes
= 0;
5450 info
.ftCreationTime
= utc_base_ft
;
5451 info
.ftLastAccessTime
= utc_base_ft
;
5452 info
.ftLastWriteTime
= utc_base_ft
;
5455 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5456 buf
->st_mode
= S_IFDIR
;
5458 buf
->st_nlink
= info
.nNumberOfLinks
;
5459 /* Might as well use file index to fake inode values, but this
5460 is not guaranteed to be unique unless we keep a handle open
5461 all the time (even then there are situations where it is
5462 not unique). Reputedly, there are at most 48 bits of info
5463 (on NTFS, presumably less on FAT). */
5464 fake_inode
= info
.nFileIndexHigh
;
5466 fake_inode
+= info
.nFileIndexLow
;
5468 /* MSVC defines _ino_t to be short; other libc's might not. */
5469 if (sizeof (buf
->st_ino
) == 2)
5470 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5472 buf
->st_ino
= fake_inode
;
5474 /* If the caller so requested, get the true file owner and group.
5475 Otherwise, consider the file to belong to the current user. */
5476 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5477 get_file_owner_and_group (NULL
, buf
);
5480 PSECURITY_DESCRIPTOR psd
= NULL
;
5482 psd
= get_file_security_desc_by_handle (fh
);
5485 get_file_owner_and_group (psd
, buf
);
5489 get_file_owner_and_group (NULL
, buf
);
5492 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5493 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5495 buf
->st_size
= info
.nFileSizeHigh
;
5496 buf
->st_size
<<= 32;
5497 buf
->st_size
+= info
.nFileSizeLow
;
5499 /* Convert timestamps to Unix format. */
5500 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5501 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5502 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5503 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5504 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5506 /* determine rwx permissions */
5507 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5508 permission
= S_IREAD
;
5510 permission
= S_IREAD
| S_IWRITE
;
5512 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5513 permission
|= S_IEXEC
;
5516 #if 0 /* no way of knowing the filename */
5517 char * p
= strrchr (name
, '.');
5519 (xstrcasecmp (p
, ".exe") == 0 ||
5520 xstrcasecmp (p
, ".com") == 0 ||
5521 xstrcasecmp (p
, ".bat") == 0 ||
5522 xstrcasecmp (p
, ".cmd") == 0))
5523 permission
|= S_IEXEC
;
5527 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5532 /* A version of 'utime' which handles directories as well as
5536 utime (const char *name
, struct utimbuf
*times
)
5538 struct utimbuf deftime
;
5545 deftime
.modtime
= deftime
.actime
= time (NULL
);
5549 if (w32_unicode_filenames
)
5551 wchar_t name_utf16
[MAX_PATH
];
5553 if (filename_to_utf16 (name
, name_utf16
) != 0)
5554 return -1; /* errno set by filename_to_utf16 */
5556 /* Need write access to set times. */
5557 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5558 /* If NAME specifies a directory, FILE_SHARE_DELETE
5559 allows other processes to delete files inside it,
5560 while we have the directory open. */
5561 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5562 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5566 char name_ansi
[MAX_PATH
];
5568 if (filename_to_ansi (name
, name_ansi
) != 0)
5569 return -1; /* errno set by filename_to_ansi */
5571 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5572 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5573 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5575 if (fh
!= INVALID_HANDLE_VALUE
)
5577 convert_from_time_t (times
->actime
, &atime
);
5578 convert_from_time_t (times
->modtime
, &mtime
);
5579 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5589 DWORD err
= GetLastError ();
5593 case ERROR_FILE_NOT_FOUND
:
5594 case ERROR_PATH_NOT_FOUND
:
5595 case ERROR_INVALID_DRIVE
:
5596 case ERROR_BAD_NETPATH
:
5597 case ERROR_DEV_NOT_EXIST
:
5598 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5599 file name includes ?s, i.e. translation to ANSI failed. */
5600 case ERROR_INVALID_NAME
:
5603 case ERROR_TOO_MANY_OPEN_FILES
:
5606 case ERROR_ACCESS_DENIED
:
5607 case ERROR_SHARING_VIOLATION
:
5620 sys_umask (int mode
)
5622 static int current_mask
;
5623 int retval
, arg
= 0;
5625 /* The only bit we really support is the write bit. Files are
5626 always readable on MS-Windows, and the execute bit does not exist
5628 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5629 to prevent access by other users on NTFS. */
5630 if ((mode
& S_IWRITE
) != 0)
5633 retval
= _umask (arg
);
5634 /* Merge into the return value the bits they've set the last time,
5635 which msvcrt.dll ignores and never returns. Emacs insists on its
5636 notion of mask being identical to what we return. */
5637 retval
|= (current_mask
& ~S_IWRITE
);
5638 current_mask
= mode
;
5644 /* Symlink-related functions. */
5645 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5646 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5650 symlink (char const *filename
, char const *linkname
)
5652 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5654 int dir_access
, filename_ends_in_slash
;
5656 /* Diagnostics follows Posix as much as possible. */
5657 if (filename
== NULL
|| linkname
== NULL
)
5667 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5669 errno
= ENAMETOOLONG
;
5673 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5674 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5680 /* Note: since empty FILENAME was already rejected, we can safely
5681 refer to FILENAME[1]. */
5682 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5684 /* Non-absolute FILENAME is understood as being relative to
5685 LINKNAME's directory. We need to prepend that directory to
5686 FILENAME to get correct results from faccessat below, since
5687 otherwise it will interpret FILENAME relative to the
5688 directory where the Emacs process runs. Note that
5689 make-symbolic-link always makes sure LINKNAME is a fully
5690 expanded file name. */
5691 char tem
[MAX_UTF8_PATH
];
5692 char *p
= linkfn
+ strlen (linkfn
);
5694 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5697 strncpy (tem
, linkfn
, p
- linkfn
);
5698 strcpy (tem
+ (p
- linkfn
), filename
);
5699 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5702 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5704 /* Since Windows distinguishes between symlinks to directories and
5705 to files, we provide a kludgy feature: if FILENAME doesn't
5706 exist, but ends in a slash, we create a symlink to directory. If
5707 FILENAME exists and is a directory, we always create a symlink to
5709 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5710 if (dir_access
== 0 || filename_ends_in_slash
)
5711 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5713 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5714 if (filename_ends_in_slash
)
5715 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5718 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5720 /* ENOSYS is set by create_symbolic_link, when it detects that
5721 the OS doesn't support the CreateSymbolicLink API. */
5722 if (errno
!= ENOSYS
)
5724 DWORD w32err
= GetLastError ();
5728 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5729 TGTFN point to the same file name, go figure. */
5731 case ERROR_FILE_EXISTS
:
5734 case ERROR_ACCESS_DENIED
:
5737 case ERROR_FILE_NOT_FOUND
:
5738 case ERROR_PATH_NOT_FOUND
:
5739 case ERROR_BAD_NETPATH
:
5740 case ERROR_INVALID_REPARSE_DATA
:
5743 case ERROR_DIRECTORY
:
5746 case ERROR_PRIVILEGE_NOT_HELD
:
5747 case ERROR_NOT_ALL_ASSIGNED
:
5750 case ERROR_DISK_FULL
:
5763 /* A quick inexpensive test of whether FILENAME identifies a file that
5764 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5765 must already be in the normalized form returned by
5766 map_w32_filename. If the symlink is to a directory, the
5767 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5769 Note: for repeated operations on many files, it is best to test
5770 whether the underlying volume actually supports symlinks, by
5771 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5772 avoid the call to this function if it doesn't. That's because the
5773 call to GetFileAttributes takes a non-negligible time, especially
5774 on non-local or removable filesystems. See stat_worker for an
5775 example of how to do that. */
5777 is_symlink (const char *filename
)
5780 wchar_t filename_w
[MAX_PATH
];
5781 char filename_a
[MAX_PATH
];
5782 WIN32_FIND_DATAW wfdw
;
5783 WIN32_FIND_DATAA wfda
;
5785 int attrs_mean_symlink
;
5787 if (w32_unicode_filenames
)
5789 filename_to_utf16 (filename
, filename_w
);
5790 attrs
= GetFileAttributesW (filename_w
);
5794 filename_to_ansi (filename
, filename_a
);
5795 attrs
= GetFileAttributesA (filename_a
);
5799 DWORD w32err
= GetLastError ();
5803 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5805 case ERROR_ACCESS_DENIED
:
5808 case ERROR_FILE_NOT_FOUND
:
5809 case ERROR_PATH_NOT_FOUND
:
5816 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5818 logon_network_drive (filename
);
5819 if (w32_unicode_filenames
)
5821 fh
= FindFirstFileW (filename_w
, &wfdw
);
5822 attrs_mean_symlink
=
5823 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5824 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5825 if (attrs_mean_symlink
)
5826 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5828 else if (_mbspbrk (filename_a
, "?"))
5830 /* filename_to_ansi failed to convert the file name. */
5836 fh
= FindFirstFileA (filename_a
, &wfda
);
5837 attrs_mean_symlink
=
5838 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5839 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5840 if (attrs_mean_symlink
)
5841 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5843 if (fh
== INVALID_HANDLE_VALUE
)
5846 return attrs_mean_symlink
;
5849 /* If NAME identifies a symbolic link, copy into BUF the file name of
5850 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5851 null-terminate the target name, even if it fits. Return the number
5852 of bytes copied, or -1 if NAME is not a symlink or any error was
5853 encountered while resolving it. The file name copied into BUF is
5854 encoded in the current ANSI codepage. */
5856 readlink (const char *name
, char *buf
, size_t buf_size
)
5859 TOKEN_PRIVILEGES privs
;
5860 int restore_privs
= 0;
5863 char resolved
[MAX_UTF8_PATH
];
5876 path
= map_w32_filename (name
, NULL
);
5878 if (strlen (path
) > MAX_UTF8_PATH
)
5880 errno
= ENAMETOOLONG
;
5885 if (is_windows_9x () == TRUE
5886 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5887 || !is_symlink (path
))
5890 errno
= EINVAL
; /* not a symlink */
5894 /* Done with simple tests, now we're in for some _real_ work. */
5895 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5897 /* Implementation note: From here and onward, don't return early,
5898 since that will fail to restore the original set of privileges of
5899 the calling thread. */
5901 retval
= -1; /* not too optimistic, are we? */
5903 /* Note: In the next call to CreateFile, we use zero as the 2nd
5904 argument because, when the symlink is a hidden/system file,
5905 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5906 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5907 and directory symlinks. */
5908 if (w32_unicode_filenames
)
5910 wchar_t path_w
[MAX_PATH
];
5912 filename_to_utf16 (path
, path_w
);
5913 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5914 FILE_FLAG_OPEN_REPARSE_POINT
5915 | FILE_FLAG_BACKUP_SEMANTICS
,
5920 char path_a
[MAX_PATH
];
5922 filename_to_ansi (path
, path_a
);
5923 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5924 FILE_FLAG_OPEN_REPARSE_POINT
5925 | FILE_FLAG_BACKUP_SEMANTICS
,
5928 if (sh
!= INVALID_HANDLE_VALUE
)
5930 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5931 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5934 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5935 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5938 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5942 /* Copy the link target name, in wide characters, from
5943 reparse_data, then convert it to multibyte encoding in
5944 the current locale's codepage. */
5948 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5950 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5951 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5952 size_t size_to_copy
= buf_size
;
5954 /* According to MSDN, PrintNameLength does not include the
5955 terminating null character. */
5956 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5957 memcpy (lwname
, lwname_src
, lwname_len
);
5958 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5959 filename_from_utf16 (lwname
, resolved
);
5960 dostounix_filename (resolved
);
5961 lname_size
= strlen (resolved
) + 1;
5962 if (lname_size
<= buf_size
)
5963 size_to_copy
= lname_size
;
5964 strncpy (buf
, resolved
, size_to_copy
);
5966 retval
= size_to_copy
;
5972 /* CreateFile failed. */
5973 DWORD w32err2
= GetLastError ();
5977 case ERROR_FILE_NOT_FOUND
:
5978 case ERROR_PATH_NOT_FOUND
:
5981 case ERROR_ACCESS_DENIED
:
5982 case ERROR_TOO_MANY_OPEN_FILES
:
5992 restore_privilege (&privs
);
6000 readlinkat (int fd
, char const *name
, char *buffer
,
6003 /* Rely on a hack: an open directory is modeled as file descriptor 0,
6004 as in fstatat. FIXME: Add proper support for readlinkat. */
6005 char fullname
[MAX_UTF8_PATH
];
6009 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
6012 errno
= ENAMETOOLONG
;
6018 return readlink (name
, buffer
, buffer_size
);
6021 /* If FILE is a symlink, return its target (stored in a static
6022 buffer); otherwise return FILE.
6024 This function repeatedly resolves symlinks in the last component of
6025 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6026 until it arrives at a file whose last component is not a symlink,
6027 or some error occurs. It returns the target of the last
6028 successfully resolved symlink in the chain. If it succeeds to
6029 resolve even a single symlink, the value returned is an absolute
6030 file name with backslashes (result of GetFullPathName). By
6031 contrast, if the original FILE is returned, it is unaltered.
6033 Note: This function can set errno even if it succeeds.
6035 Implementation note: we only resolve the last portion ("basename")
6036 of the argument FILE and of each following file in the chain,
6037 disregarding any possible symlinks in its leading directories.
6038 This is because Windows system calls and library functions
6039 transparently resolve symlinks in leading directories and return
6040 correct information, as long as the basename is not a symlink. */
6042 chase_symlinks (const char *file
)
6044 static char target
[MAX_UTF8_PATH
];
6045 char link
[MAX_UTF8_PATH
];
6046 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
6047 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
6048 ssize_t res
, link_len
;
6051 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
6052 return (char *)file
;
6054 if (w32_unicode_filenames
)
6056 wchar_t file_w
[MAX_PATH
];
6058 filename_to_utf16 (file
, file_w
);
6059 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
6060 return (char *)file
;
6061 filename_from_utf16 (link_w
, link
);
6065 char file_a
[MAX_PATH
];
6067 filename_to_ansi (file
, file_a
);
6068 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
6069 return (char *)file
;
6070 filename_from_ansi (link_a
, link
);
6072 link_len
= strlen (link
);
6077 /* Remove trailing slashes, as we want to resolve the last
6078 non-trivial part of the link name. */
6079 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
6080 link
[link_len
--] = '\0';
6082 res
= readlink (link
, target
, MAX_UTF8_PATH
);
6086 if (!(IS_DEVICE_SEP (target
[1])
6087 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
6089 /* Target is relative. Append it to the directory part of
6090 the symlink, then copy the result back to target. */
6091 char *p
= link
+ link_len
;
6093 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
6096 strcpy (target
, link
);
6098 /* Resolve any "." and ".." to get a fully-qualified file name
6100 if (w32_unicode_filenames
)
6102 filename_to_utf16 (target
, target_w
);
6103 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
6105 filename_from_utf16 (link_w
, link
);
6109 filename_to_ansi (target
, target_a
);
6110 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
6112 filename_from_ansi (link_a
, link
);
6114 link_len
= strlen (link
);
6116 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6118 if (loop_count
> 100)
6121 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6122 return (char *)file
;
6127 /* Posix ACL emulation. */
6130 acl_valid (acl_t acl
)
6132 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6136 acl_to_text (acl_t acl
, ssize_t
*size
)
6139 SECURITY_INFORMATION flags
=
6140 OWNER_SECURITY_INFORMATION
|
6141 GROUP_SECURITY_INFORMATION
|
6142 DACL_SECURITY_INFORMATION
;
6143 char *retval
= NULL
;
6149 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6152 /* We don't want to mix heaps, so we duplicate the string in our
6153 heap and free the one allocated by the API. */
6154 retval
= xstrdup (str_acl
);
6157 LocalFree (str_acl
);
6159 else if (errno
!= ENOTSUP
)
6166 acl_from_text (const char *acl_str
)
6168 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6174 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6177 retval
= xmalloc (sd_size
);
6178 memcpy (retval
, psd
, sd_size
);
6181 else if (errno
!= ENOTSUP
)
6188 acl_free (void *ptr
)
6195 acl_get_file (const char *fname
, acl_type_t type
)
6197 PSECURITY_DESCRIPTOR psd
= NULL
;
6198 const char *filename
;
6200 if (type
== ACL_TYPE_ACCESS
)
6203 SECURITY_INFORMATION si
=
6204 OWNER_SECURITY_INFORMATION
|
6205 GROUP_SECURITY_INFORMATION
|
6206 DACL_SECURITY_INFORMATION
;
6209 filename
= map_w32_filename (fname
, NULL
);
6210 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6211 fname
= chase_symlinks (filename
);
6216 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6217 && errno
!= ENOTSUP
)
6219 err
= GetLastError ();
6220 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6222 psd
= xmalloc (sd_len
);
6223 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6230 else if (err
== ERROR_FILE_NOT_FOUND
6231 || err
== ERROR_PATH_NOT_FOUND
6232 /* ERROR_INVALID_NAME is what we get if
6233 w32-unicode-filenames is nil and the file cannot
6234 be encoded in the current ANSI codepage. */
6235 || err
== ERROR_INVALID_NAME
)
6243 else if (type
!= ACL_TYPE_DEFAULT
)
6250 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6252 TOKEN_PRIVILEGES old1
, old2
;
6254 int st
= 0, retval
= -1;
6255 SECURITY_INFORMATION flags
= 0;
6256 PSID psidOwner
, psidGroup
;
6261 const char *filename
;
6263 if (acl_valid (acl
) != 0
6264 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6270 if (type
== ACL_TYPE_DEFAULT
)
6276 filename
= map_w32_filename (fname
, NULL
);
6277 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6278 fname
= chase_symlinks (filename
);
6282 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6285 flags
|= OWNER_SECURITY_INFORMATION
;
6286 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6289 flags
|= GROUP_SECURITY_INFORMATION
;
6290 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6293 flags
|= DACL_SECURITY_INFORMATION
;
6297 /* According to KB-245153, setting the owner will succeed if either:
6298 (1) the caller is the user who will be the new owner, and has the
6299 SE_TAKE_OWNERSHIP privilege, or
6300 (2) the caller has the SE_RESTORE privilege, in which case she can
6301 set any valid user or group as the owner
6303 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6304 privileges, and disregard any failures in obtaining them. If
6305 these privileges cannot be obtained, and do not already exist in
6306 the calling thread's security token, this function could fail
6308 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6310 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6315 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6316 DACL inheritance is involved, but it seems to preserve ownership
6317 better than SetNamedSecurityInfo, which is important e.g., in
6319 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6321 err
= GetLastError ();
6323 if (errno
!= ENOTSUP
)
6324 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6325 psidOwner
, psidGroup
, pacl
, NULL
);
6328 err
= ERROR_SUCCESS
;
6329 if (err
!= ERROR_SUCCESS
)
6331 if (errno
== ENOTSUP
)
6333 else if (err
== ERROR_INVALID_OWNER
6334 || err
== ERROR_NOT_ALL_ASSIGNED
6335 || err
== ERROR_ACCESS_DENIED
)
6337 /* Maybe the requested ACL and the one the file already has
6338 are identical, in which case we can silently ignore the
6339 failure. (And no, Windows doesn't.) */
6340 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6345 char *acl_from
= acl_to_text (current_acl
, NULL
);
6346 char *acl_to
= acl_to_text (acl
, NULL
);
6348 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6354 acl_free (acl_from
);
6357 acl_free (current_acl
);
6360 else if (err
== ERROR_FILE_NOT_FOUND
6361 || err
== ERROR_PATH_NOT_FOUND
6362 /* ERROR_INVALID_NAME is what we get if
6363 w32-unicode-filenames is nil and the file cannot be
6364 encoded in the current ANSI codepage. */
6365 || err
== ERROR_INVALID_NAME
)
6379 restore_privilege (&old2
);
6380 restore_privilege (&old1
);
6388 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6389 have a fixed max size for file names, so we don't need the kind of
6390 alloc/malloc/realloc dance the gnulib version does. We also don't
6391 support FD-relative symlinks. */
6393 careadlinkat (int fd
, char const *filename
,
6394 char *buffer
, size_t buffer_size
,
6395 struct allocator
const *alloc
,
6396 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6398 char linkname
[MAX_UTF8_PATH
];
6401 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6405 char *retval
= buffer
;
6407 linkname
[link_size
++] = '\0';
6408 if (link_size
> buffer_size
)
6409 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6411 memcpy (retval
, linkname
, link_size
);
6419 w32_copy_file (const char *from
, const char *to
,
6420 int keep_time
, int preserve_ownership
, int copy_acls
)
6424 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6425 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6427 /* We ignore preserve_ownership for now. */
6428 preserve_ownership
= preserve_ownership
;
6432 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6433 if (acl
== NULL
&& acl_errno_valid (errno
))
6436 if (w32_unicode_filenames
)
6438 filename_to_utf16 (from
, from_w
);
6439 filename_to_utf16 (to
, to_w
);
6440 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6444 filename_to_ansi (from
, from_a
);
6445 filename_to_ansi (to
, to_a
);
6446 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6450 /* CopyFile doesn't set errno when it fails. By far the most
6451 "popular" reason is that the target is read-only. */
6452 DWORD err
= GetLastError ();
6456 case ERROR_FILE_NOT_FOUND
:
6459 case ERROR_ACCESS_DENIED
:
6462 case ERROR_ENCRYPTION_FAILED
:
6474 /* CopyFile retains the timestamp by default. However, see
6475 "Community Additions" for CopyFile: it sounds like that is not
6476 entirely true. Testing on Windows XP confirms that modified time
6477 is copied, but creation and last-access times are not.
6479 else if (!keep_time
)
6481 struct timespec now
;
6484 if (w32_unicode_filenames
)
6486 /* Ensure file is writable while its times are set. */
6487 attributes
= GetFileAttributesW (to_w
);
6488 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6489 now
= current_timespec ();
6490 if (set_file_times (-1, to
, now
, now
))
6492 /* Restore original attributes. */
6493 SetFileAttributesW (to_w
, attributes
);
6498 /* Restore original attributes. */
6499 SetFileAttributesW (to_w
, attributes
);
6503 attributes
= GetFileAttributesA (to_a
);
6504 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6505 now
= current_timespec ();
6506 if (set_file_times (-1, to
, now
, now
))
6508 SetFileAttributesA (to_a
, attributes
);
6513 SetFileAttributesA (to_a
, attributes
);
6519 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6521 if (fail
&& acl_errno_valid (errno
))
6529 /* Support for browsing other processes and their attributes. See
6530 process.c for the Lisp bindings. */
6532 /* Helper wrapper functions. */
6534 static HANDLE WINAPI
6535 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6537 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6539 if (g_b_init_create_toolhelp32_snapshot
== 0)
6541 g_b_init_create_toolhelp32_snapshot
= 1;
6542 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6543 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6544 "CreateToolhelp32Snapshot");
6546 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6548 return INVALID_HANDLE_VALUE
;
6550 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6554 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6556 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6558 if (g_b_init_process32_first
== 0)
6560 g_b_init_process32_first
= 1;
6561 s_pfn_Process32_First
= (Process32First_Proc
)
6562 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6565 if (s_pfn_Process32_First
== NULL
)
6569 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6573 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6575 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6577 if (g_b_init_process32_next
== 0)
6579 g_b_init_process32_next
= 1;
6580 s_pfn_Process32_Next
= (Process32Next_Proc
)
6581 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6584 if (s_pfn_Process32_Next
== NULL
)
6588 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6592 open_thread_token (HANDLE ThreadHandle
,
6593 DWORD DesiredAccess
,
6595 PHANDLE TokenHandle
)
6597 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6598 HMODULE hm_advapi32
= NULL
;
6599 if (is_windows_9x () == TRUE
)
6601 SetLastError (ERROR_NOT_SUPPORTED
);
6604 if (g_b_init_open_thread_token
== 0)
6606 g_b_init_open_thread_token
= 1;
6607 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6608 s_pfn_Open_Thread_Token
=
6609 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6611 if (s_pfn_Open_Thread_Token
== NULL
)
6613 SetLastError (ERROR_NOT_SUPPORTED
);
6617 s_pfn_Open_Thread_Token (
6626 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6628 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6629 HMODULE hm_advapi32
= NULL
;
6630 if (is_windows_9x () == TRUE
)
6634 if (g_b_init_impersonate_self
== 0)
6636 g_b_init_impersonate_self
= 1;
6637 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6638 s_pfn_Impersonate_Self
=
6639 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6641 if (s_pfn_Impersonate_Self
== NULL
)
6645 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6649 revert_to_self (void)
6651 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6652 HMODULE hm_advapi32
= NULL
;
6653 if (is_windows_9x () == TRUE
)
6657 if (g_b_init_revert_to_self
== 0)
6659 g_b_init_revert_to_self
= 1;
6660 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6661 s_pfn_Revert_To_Self
=
6662 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6664 if (s_pfn_Revert_To_Self
== NULL
)
6668 return s_pfn_Revert_To_Self ();
6672 get_process_memory_info (HANDLE h_proc
,
6673 PPROCESS_MEMORY_COUNTERS mem_counters
,
6676 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6677 HMODULE hm_psapi
= NULL
;
6678 if (is_windows_9x () == TRUE
)
6682 if (g_b_init_get_process_memory_info
== 0)
6684 g_b_init_get_process_memory_info
= 1;
6685 hm_psapi
= LoadLibrary ("Psapi.dll");
6687 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6688 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6690 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6694 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6698 get_process_working_set_size (HANDLE h_proc
,
6702 static GetProcessWorkingSetSize_Proc
6703 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6705 if (is_windows_9x () == TRUE
)
6709 if (g_b_init_get_process_working_set_size
== 0)
6711 g_b_init_get_process_working_set_size
= 1;
6712 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6713 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6714 "GetProcessWorkingSetSize");
6716 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6720 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6724 global_memory_status (MEMORYSTATUS
*buf
)
6726 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6728 if (is_windows_9x () == TRUE
)
6732 if (g_b_init_global_memory_status
== 0)
6734 g_b_init_global_memory_status
= 1;
6735 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6736 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6737 "GlobalMemoryStatus");
6739 if (s_pfn_Global_Memory_Status
== NULL
)
6743 return s_pfn_Global_Memory_Status (buf
);
6747 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6749 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6751 if (is_windows_9x () == TRUE
)
6755 if (g_b_init_global_memory_status_ex
== 0)
6757 g_b_init_global_memory_status_ex
= 1;
6758 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6759 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6760 "GlobalMemoryStatusEx");
6762 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6766 return s_pfn_Global_Memory_Status_Ex (buf
);
6770 list_system_processes (void)
6772 Lisp_Object proclist
= Qnil
;
6775 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6777 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6779 PROCESSENTRY32 proc_entry
;
6783 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6784 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6785 res
= process32_next (h_snapshot
, &proc_entry
))
6787 proc_id
= proc_entry
.th32ProcessID
;
6788 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6791 CloseHandle (h_snapshot
);
6792 proclist
= Fnreverse (proclist
);
6799 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6801 TOKEN_PRIVILEGES priv
;
6802 DWORD priv_size
= sizeof (priv
);
6803 DWORD opriv_size
= sizeof (*old_priv
);
6804 HANDLE h_token
= NULL
;
6805 HANDLE h_thread
= GetCurrentThread ();
6809 res
= open_thread_token (h_thread
,
6810 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6812 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6814 if (impersonate_self (SecurityImpersonation
))
6815 res
= open_thread_token (h_thread
,
6816 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6821 priv
.PrivilegeCount
= 1;
6822 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6823 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6824 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6825 old_priv
, &opriv_size
)
6826 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6830 CloseHandle (h_token
);
6836 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6838 DWORD priv_size
= sizeof (*priv
);
6839 HANDLE h_token
= NULL
;
6842 if (open_thread_token (GetCurrentThread (),
6843 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6846 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6847 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6851 CloseHandle (h_token
);
6857 ltime (ULONGLONG time_100ns
)
6859 ULONGLONG time_sec
= time_100ns
/ 10000000;
6860 int subsec
= time_100ns
% 10000000;
6861 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6862 subsec
/ 10, subsec
% 10 * 100000);
6865 #define U64_TO_LISP_TIME(time) ltime (time)
6868 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6869 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6872 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6873 ULONGLONG tem1
, tem2
, tem3
, tem
;
6876 || !get_process_times_fn
6877 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6878 &ft_kernel
, &ft_user
))
6881 GetSystemTimeAsFileTime (&ft_current
);
6883 FILETIME_TO_U64 (tem1
, ft_kernel
);
6884 *stime
= U64_TO_LISP_TIME (tem1
);
6886 FILETIME_TO_U64 (tem2
, ft_user
);
6887 *utime
= U64_TO_LISP_TIME (tem2
);
6890 *ttime
= U64_TO_LISP_TIME (tem3
);
6892 FILETIME_TO_U64 (tem
, ft_creation
);
6893 /* Process no 4 (System) returns zero creation time. */
6896 *ctime
= U64_TO_LISP_TIME (tem
);
6900 FILETIME_TO_U64 (tem3
, ft_current
);
6901 tem
= (tem3
- utc_base
) - tem
;
6903 *etime
= U64_TO_LISP_TIME (tem
);
6907 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6918 system_process_attributes (Lisp_Object pid
)
6920 Lisp_Object attrs
= Qnil
;
6921 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6922 HANDLE h_snapshot
, h_proc
;
6925 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6926 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6927 DWORD glength
= sizeof (gname
);
6928 HANDLE token
= NULL
;
6929 SID_NAME_USE user_type
;
6930 unsigned char *buf
= NULL
;
6932 TOKEN_USER user_token
;
6933 TOKEN_PRIMARY_GROUP group_token
;
6936 PROCESS_MEMORY_COUNTERS mem
;
6937 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6938 SIZE_T minrss
, maxrss
;
6940 MEMORY_STATUS_EX memstex
;
6941 double totphys
= 0.0;
6942 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6944 BOOL result
= FALSE
;
6946 CHECK_NUMBER_OR_FLOAT (pid
);
6947 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6949 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6951 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6956 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6957 for (res
= process32_first (h_snapshot
, &pe
); res
;
6958 res
= process32_next (h_snapshot
, &pe
))
6960 if (proc_id
== pe
.th32ProcessID
)
6963 decoded_cmd
= build_string ("Idle");
6966 /* Decode the command name from locale-specific
6968 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6971 code_convert_string_norecord (cmd_str
,
6972 Vlocale_coding_system
, 0);
6974 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6975 attrs
= Fcons (Fcons (Qppid
,
6976 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6978 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6980 attrs
= Fcons (Fcons (Qthcount
,
6981 make_fixnum_or_float (pe
.cntThreads
)),
6988 CloseHandle (h_snapshot
);
6994 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6996 /* If we were denied a handle to the process, try again after
6997 enabling the SeDebugPrivilege in our process. */
7000 TOKEN_PRIVILEGES priv_current
;
7002 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
7004 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7006 restore_privilege (&priv_current
);
7012 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
7015 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
7016 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7018 buf
= xmalloc (blen
);
7019 result
= get_token_information (token
, TokenUser
,
7020 (LPVOID
)buf
, blen
, &needed
);
7023 memcpy (&user_token
, buf
, sizeof (user_token
));
7024 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
7026 euid
= get_rid (user_token
.User
.Sid
);
7027 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
7032 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
7035 strcpy (uname
, "unknown");
7039 ulength
= strlen (uname
);
7045 /* Determine a reasonable euid and gid values. */
7046 if (xstrcasecmp ("administrator", uname
) == 0)
7048 euid
= 500; /* well-known Administrator uid */
7049 egid
= 513; /* well-known None gid */
7053 /* Get group id and name. */
7054 result
= get_token_information (token
, TokenPrimaryGroup
,
7055 (LPVOID
)buf
, blen
, &needed
);
7056 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7058 buf
= xrealloc (buf
, blen
= needed
);
7059 result
= get_token_information (token
, TokenPrimaryGroup
,
7060 (LPVOID
)buf
, blen
, &needed
);
7064 memcpy (&group_token
, buf
, sizeof (group_token
));
7065 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
7067 egid
= get_rid (group_token
.PrimaryGroup
);
7068 dlength
= sizeof (domain
);
7070 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
7071 gname
, &glength
, NULL
, &dlength
,
7074 w32_add_to_cache (group_token
.PrimaryGroup
,
7078 strcpy (gname
, "None");
7082 glength
= strlen (gname
);
7090 if (!is_windows_9x ())
7092 /* We couldn't open the process token, presumably because of
7093 insufficient access rights. Assume this process is run
7095 strcpy (uname
, "SYSTEM");
7096 strcpy (gname
, "None");
7097 euid
= 18; /* SYSTEM */
7098 egid
= 513; /* None */
7099 glength
= strlen (gname
);
7100 ulength
= strlen (uname
);
7102 /* If we are running under Windows 9X, where security calls are
7103 not supported, we assume all processes are run by the current
7105 else if (GetUserName (uname
, &ulength
))
7107 if (xstrcasecmp ("administrator", uname
) == 0)
7112 strcpy (gname
, "None");
7113 glength
= strlen (gname
);
7114 ulength
= strlen (uname
);
7120 strcpy (uname
, "administrator");
7121 ulength
= strlen (uname
);
7122 strcpy (gname
, "None");
7123 glength
= strlen (gname
);
7126 CloseHandle (token
);
7129 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7130 tem
= make_unibyte_string (uname
, ulength
);
7131 attrs
= Fcons (Fcons (Quser
,
7132 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7134 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7135 tem
= make_unibyte_string (gname
, glength
);
7136 attrs
= Fcons (Fcons (Qgroup
,
7137 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7140 if (global_memory_status_ex (&memstex
))
7141 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7142 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7144 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7145 double, so we need to do this for it... */
7147 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7148 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7149 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7151 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7153 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7154 else if (global_memory_status (&memst
))
7155 totphys
= memst
.dwTotalPhys
/ 1024.0;
7158 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7161 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7163 attrs
= Fcons (Fcons (Qmajflt
,
7164 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7166 attrs
= Fcons (Fcons (Qvsize
,
7167 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7169 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7171 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7174 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7176 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7178 attrs
= Fcons (Fcons (Qmajflt
,
7179 make_fixnum_or_float (mem
.PageFaultCount
)),
7181 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7183 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7186 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7188 DWORD rss
= maxrss
/ 1024;
7190 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7192 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7195 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7197 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7198 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7199 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7200 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7201 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7202 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7205 /* FIXME: Retrieve command line by walking the PEB of the process. */
7208 CloseHandle (h_proc
);
7213 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7214 unsigned long long *totalswap
, unsigned long long *freeswap
)
7217 MEMORY_STATUS_EX memstex
;
7219 /* Use GlobalMemoryStatusEx if available, as it can report more than
7221 if (global_memory_status_ex (&memstex
))
7223 *totalram
= memstex
.ullTotalPhys
;
7224 *freeram
= memstex
.ullAvailPhys
;
7225 *totalswap
= memstex
.ullTotalPageFile
;
7226 *freeswap
= memstex
.ullAvailPageFile
;
7229 else if (global_memory_status (&memst
))
7231 *totalram
= memst
.dwTotalPhys
;
7232 *freeram
= memst
.dwAvailPhys
;
7233 *totalswap
= memst
.dwTotalPageFile
;
7234 *freeswap
= memst
.dwAvailPageFile
;
7242 /* Wrappers for winsock functions to map between our file descriptors
7243 and winsock's handles; also set h_errno for convenience.
7245 To allow Emacs to run on systems which don't have winsock support
7246 installed, we dynamically link to winsock on startup if present, and
7247 otherwise provide the minimum necessary functionality
7248 (eg. gethostname). */
7250 /* function pointers for relevant socket functions */
7251 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7252 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7253 int (PASCAL
*pfn_WSAGetLastError
) (void);
7254 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7255 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7256 WSANETWORKEVENTS
*NetworkEvents
);
7258 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7259 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7260 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7261 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7262 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7263 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7264 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7265 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7266 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7267 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7268 int (PASCAL
*pfn_WSACleanup
) (void);
7270 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7271 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7272 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7273 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7274 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7275 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7276 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7277 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7278 const char * optval
, int optlen
);
7279 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7280 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7282 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7283 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7284 struct sockaddr
* from
, int * fromlen
);
7285 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7286 const struct sockaddr
* to
, int tolen
);
7288 int (PASCAL
*pfn_getaddrinfo
) (const char *, const char *,
7289 const struct addrinfo
*, struct addrinfo
**);
7290 void (PASCAL
*pfn_freeaddrinfo
) (struct addrinfo
*);
7292 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7293 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7294 #ifndef HANDLE_FLAG_INHERIT
7295 #define HANDLE_FLAG_INHERIT 1
7299 static int winsock_inuse
;
7301 BOOL
term_winsock (void);
7306 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7308 release_listen_threads ();
7309 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7310 after WSAStartup returns successfully, but it seems reasonable
7311 to allow unloading winsock anyway in that case. */
7312 if (pfn_WSACleanup () == 0 ||
7313 pfn_WSAGetLastError () == WSAENETDOWN
)
7315 if (FreeLibrary (winsock_lib
))
7324 init_winsock (int load_now
)
7326 WSADATA winsockData
;
7328 if (winsock_lib
!= NULL
)
7331 pfn_SetHandleInformation
7332 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7333 "SetHandleInformation");
7335 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7337 if (winsock_lib
!= NULL
)
7339 /* dynamically link to socket functions */
7341 #define LOAD_PROC(fn) \
7342 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7345 LOAD_PROC (WSAStartup
);
7346 LOAD_PROC (WSASetLastError
);
7347 LOAD_PROC (WSAGetLastError
);
7348 LOAD_PROC (WSAEventSelect
);
7349 LOAD_PROC (WSAEnumNetworkEvents
);
7350 LOAD_PROC (WSACreateEvent
);
7351 LOAD_PROC (WSACloseEvent
);
7354 LOAD_PROC (connect
);
7355 LOAD_PROC (ioctlsocket
);
7358 LOAD_PROC (closesocket
);
7359 LOAD_PROC (shutdown
);
7362 LOAD_PROC (inet_addr
);
7363 LOAD_PROC (gethostname
);
7364 LOAD_PROC (gethostbyname
);
7365 LOAD_PROC (getservbyname
);
7366 LOAD_PROC (getpeername
);
7367 LOAD_PROC (WSACleanup
);
7368 LOAD_PROC (setsockopt
);
7370 LOAD_PROC (getsockname
);
7372 LOAD_PROC (recvfrom
);
7376 /* Try loading functions not available before XP. */
7377 pfn_getaddrinfo
= (void *) GetProcAddress (winsock_lib
, "getaddrinfo");
7378 pfn_freeaddrinfo
= (void *) GetProcAddress (winsock_lib
, "freeaddrinfo");
7379 /* Paranoia: these two functions should go together, so if one
7380 is absent, we cannot use the other. */
7381 if (pfn_getaddrinfo
== NULL
)
7382 pfn_freeaddrinfo
= NULL
;
7383 else if (pfn_freeaddrinfo
== NULL
)
7384 pfn_getaddrinfo
= NULL
;
7386 /* specify version 1.1 of winsock */
7387 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7389 if (winsockData
.wVersion
!= 0x101)
7394 /* Report that winsock exists and is usable, but leave
7395 socket functions disabled. I am assuming that calling
7396 WSAStartup does not require any network interaction,
7397 and in particular does not cause or require a dial-up
7398 connection to be established. */
7401 FreeLibrary (winsock_lib
);
7409 FreeLibrary (winsock_lib
);
7419 /* Function to map winsock error codes to errno codes for those errno
7420 code defined in errno.h (errno values not defined by errno.h are
7421 already in nt/inc/sys/socket.h). */
7428 if (winsock_lib
== NULL
)
7431 wsa_err
= pfn_WSAGetLastError ();
7435 case WSAEACCES
: errno
= EACCES
; break;
7436 case WSAEBADF
: errno
= EBADF
; break;
7437 case WSAEFAULT
: errno
= EFAULT
; break;
7438 case WSAEINTR
: errno
= EINTR
; break;
7439 case WSAEINVAL
: errno
= EINVAL
; break;
7440 case WSAEMFILE
: errno
= EMFILE
; break;
7441 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7442 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7443 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7444 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7445 default: errno
= wsa_err
; break;
7453 if (winsock_lib
!= NULL
)
7454 pfn_WSASetLastError (0);
7457 /* Extend strerror to handle the winsock-specific error codes. */
7461 } _wsa_errlist
[] = {
7462 {WSAEINTR
, "Interrupted function call"},
7463 {WSAEBADF
, "Bad file descriptor"},
7464 {WSAEACCES
, "Permission denied"},
7465 {WSAEFAULT
, "Bad address"},
7466 {WSAEINVAL
, "Invalid argument"},
7467 {WSAEMFILE
, "Too many open files"},
7469 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7470 {WSAEINPROGRESS
, "Operation now in progress"},
7471 {WSAEALREADY
, "Operation already in progress"},
7472 {WSAENOTSOCK
, "Socket operation on non-socket"},
7473 {WSAEDESTADDRREQ
, "Destination address required"},
7474 {WSAEMSGSIZE
, "Message too long"},
7475 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7476 {WSAENOPROTOOPT
, "Bad protocol option"},
7477 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7478 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7479 {WSAEOPNOTSUPP
, "Operation not supported"},
7480 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7481 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7482 {WSAEADDRINUSE
, "Address already in use"},
7483 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7484 {WSAENETDOWN
, "Network is down"},
7485 {WSAENETUNREACH
, "Network is unreachable"},
7486 {WSAENETRESET
, "Network dropped connection on reset"},
7487 {WSAECONNABORTED
, "Software caused connection abort"},
7488 {WSAECONNRESET
, "Connection reset by peer"},
7489 {WSAENOBUFS
, "No buffer space available"},
7490 {WSAEISCONN
, "Socket is already connected"},
7491 {WSAENOTCONN
, "Socket is not connected"},
7492 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7493 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7494 {WSAETIMEDOUT
, "Connection timed out"},
7495 {WSAECONNREFUSED
, "Connection refused"},
7496 {WSAELOOP
, "Network loop"}, /* not sure */
7497 {WSAENAMETOOLONG
, "Name is too long"},
7498 {WSAEHOSTDOWN
, "Host is down"},
7499 {WSAEHOSTUNREACH
, "No route to host"},
7500 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7501 {WSAEPROCLIM
, "Too many processes"},
7502 {WSAEUSERS
, "Too many users"}, /* not sure */
7503 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7504 {WSAESTALE
, "Data is stale"}, /* not sure */
7505 {WSAEREMOTE
, "Remote error"}, /* not sure */
7507 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7508 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7509 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7510 {WSAEDISCON
, "Graceful shutdown in progress"},
7512 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7513 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7514 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7515 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7516 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7517 {WSASYSCALLFAILURE
, "System call failure"},
7518 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7519 {WSATYPE_NOT_FOUND
, "Class type not found"},
7520 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7521 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7522 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7525 {WSAHOST_NOT_FOUND
, "Host not found"},
7526 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7527 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7528 {WSANO_DATA
, "Valid name, no data record of requested type"},
7534 sys_strerror (int error_no
)
7537 static char unknown_msg
[40];
7539 if (error_no
>= 0 && error_no
< sys_nerr
)
7540 return sys_errlist
[error_no
];
7542 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7543 if (_wsa_errlist
[i
].errnum
== error_no
)
7544 return (char *)_wsa_errlist
[i
].msg
;
7546 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7550 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7551 but I believe the method of keeping the socket handle separate (and
7552 insuring it is not inheritable) is the correct one. */
7554 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7556 static int socket_to_fd (SOCKET s
);
7559 sys_socket (int af
, int type
, int protocol
)
7563 if (winsock_lib
== NULL
)
7571 /* call the real socket function */
7572 s
= pfn_socket (af
, type
, protocol
);
7574 if (s
!= INVALID_SOCKET
)
7575 return socket_to_fd (s
);
7581 /* Convert a SOCKET to a file descriptor. */
7583 socket_to_fd (SOCKET s
)
7588 /* Although under NT 3.5 _open_osfhandle will accept a socket
7589 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7590 that does not work under NT 3.1. However, we can get the same
7591 effect by using a backdoor function to replace an existing
7592 descriptor handle with the one we want. */
7594 /* allocate a file descriptor (with appropriate flags) */
7595 fd
= _open ("NUL:", _O_RDWR
);
7598 /* Make a non-inheritable copy of the socket handle. Note
7599 that it is possible that sockets aren't actually kernel
7600 handles, which appears to be the case on Windows 9x when
7601 the MS Proxy winsock client is installed. */
7603 /* Apparently there is a bug in NT 3.51 with some service
7604 packs, which prevents using DuplicateHandle to make a
7605 socket handle non-inheritable (causes WSACleanup to
7606 hang). The work-around is to use SetHandleInformation
7607 instead if it is available and implemented. */
7608 if (pfn_SetHandleInformation
)
7610 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7614 HANDLE parent
= GetCurrentProcess ();
7615 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7617 if (DuplicateHandle (parent
,
7623 DUPLICATE_SAME_ACCESS
))
7625 /* It is possible that DuplicateHandle succeeds even
7626 though the socket wasn't really a kernel handle,
7627 because a real handle has the same value. So
7628 test whether the new handle really is a socket. */
7629 unsigned long nonblocking
= 0;
7630 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7632 pfn_closesocket (s
);
7637 CloseHandle (new_s
);
7642 eassert (fd
< MAXDESC
);
7643 fd_info
[fd
].hnd
= (HANDLE
) s
;
7645 /* set our own internal flags */
7646 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7652 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7654 /* attach child_process to fd_info */
7655 if (fd_info
[ fd
].cp
!= NULL
)
7657 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7661 fd_info
[ fd
].cp
= cp
;
7664 winsock_inuse
++; /* count open sockets */
7672 pfn_closesocket (s
);
7678 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7680 if (winsock_lib
== NULL
)
7683 return SOCKET_ERROR
;
7687 if (fd_info
[s
].flags
& FILE_SOCKET
)
7689 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7690 if (rc
== SOCKET_ERROR
)
7695 return SOCKET_ERROR
;
7699 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7701 if (winsock_lib
== NULL
)
7704 return SOCKET_ERROR
;
7708 if (fd_info
[s
].flags
& FILE_SOCKET
)
7710 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7711 if (rc
== SOCKET_ERROR
)
7714 /* If this is a non-blocking 'connect', set the bit in flags
7715 that will tell reader_thread to wait for connection
7716 before trying to read. */
7717 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7719 errno
= EINPROGRESS
; /* that's what process.c expects */
7720 fd_info
[s
].flags
|= FILE_CONNECT
;
7726 return SOCKET_ERROR
;
7730 sys_htons (u_short hostshort
)
7732 return (winsock_lib
!= NULL
) ?
7733 pfn_htons (hostshort
) : hostshort
;
7737 sys_ntohs (u_short netshort
)
7739 return (winsock_lib
!= NULL
) ?
7740 pfn_ntohs (netshort
) : netshort
;
7744 sys_inet_addr (const char * cp
)
7746 return (winsock_lib
!= NULL
) ?
7747 pfn_inet_addr (cp
) : INADDR_NONE
;
7751 sys_gethostname (char * name
, int namelen
)
7753 if (winsock_lib
!= NULL
)
7758 retval
= pfn_gethostname (name
, namelen
);
7759 if (retval
== SOCKET_ERROR
)
7764 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7765 return !GetComputerName (name
, (DWORD
*)&namelen
);
7768 return SOCKET_ERROR
;
7772 sys_gethostbyname (const char * name
)
7774 struct hostent
* host
;
7775 int h_err
= h_errno
;
7777 if (winsock_lib
== NULL
)
7779 h_errno
= NO_RECOVERY
;
7785 host
= pfn_gethostbyname (name
);
7797 sys_getservbyname (const char * name
, const char * proto
)
7799 struct servent
* serv
;
7801 if (winsock_lib
== NULL
)
7808 serv
= pfn_getservbyname (name
, proto
);
7815 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7817 if (winsock_lib
== NULL
)
7820 return SOCKET_ERROR
;
7824 if (fd_info
[s
].flags
& FILE_SOCKET
)
7826 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7827 if (rc
== SOCKET_ERROR
)
7832 return SOCKET_ERROR
;
7836 sys_getaddrinfo (const char *node
, const char *service
,
7837 const struct addrinfo
*hints
, struct addrinfo
**res
)
7841 if (winsock_lib
== NULL
)
7844 return SOCKET_ERROR
;
7848 if (pfn_getaddrinfo
)
7849 rc
= pfn_getaddrinfo (node
, service
, hints
, res
);
7853 struct hostent
*host_info
;
7854 struct gai_storage
{
7855 struct addrinfo addrinfo
;
7856 struct sockaddr_in sockaddr_in
;
7859 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7860 if (hints
&& hints
->ai_flags
!= 0)
7862 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7864 return WSAHOST_NOT_FOUND
;
7868 const char *protocol
=
7869 (hints
&& hints
->ai_socktype
== SOCK_DGRAM
) ? "udp" : "tcp";
7870 struct servent
*srv
= sys_getservbyname (service
, protocol
);
7874 else if (*service
>= '0' && *service
<= '9')
7878 port
= strtoul (service
, &endp
, 10);
7879 if (*endp
|| port
> 65536)
7880 return WSAHOST_NOT_FOUND
;
7881 port
= sys_htons ((unsigned short) port
);
7884 return WSAHOST_NOT_FOUND
;
7887 gai_storage
= xzalloc (sizeof *gai_storage
);
7888 gai_storage
->sockaddr_in
.sin_port
= port
;
7889 host_info
= sys_gethostbyname (node
);
7892 memcpy (&gai_storage
->sockaddr_in
.sin_addr
,
7893 host_info
->h_addr
, host_info
->h_length
);
7894 gai_storage
->sockaddr_in
.sin_family
= host_info
->h_addrtype
;
7898 /* Attempt to interpret host as numeric inet address. */
7899 unsigned long numeric_addr
= sys_inet_addr (node
);
7901 if (numeric_addr
== -1)
7904 return WSAHOST_NOT_FOUND
;
7907 memcpy (&gai_storage
->sockaddr_in
.sin_addr
, &numeric_addr
,
7908 sizeof (gai_storage
->sockaddr_in
.sin_addr
));
7909 gai_storage
->sockaddr_in
.sin_family
= (hints
) ? hints
->ai_family
: 0;
7912 gai_storage
->addrinfo
.ai_addr
=
7913 (struct sockaddr
*)&gai_storage
->sockaddr_in
;
7914 gai_storage
->addrinfo
.ai_addrlen
= sizeof (gai_storage
->sockaddr_in
);
7915 gai_storage
->addrinfo
.ai_protocol
= (hints
) ? hints
->ai_protocol
: 0;
7916 gai_storage
->addrinfo
.ai_socktype
= (hints
) ? hints
->ai_socktype
: 0;
7917 gai_storage
->addrinfo
.ai_family
= gai_storage
->sockaddr_in
.sin_family
;
7918 gai_storage
->addrinfo
.ai_next
= NULL
;
7920 *res
= &gai_storage
->addrinfo
;
7928 sys_freeaddrinfo (struct addrinfo
*ai
)
7930 if (winsock_lib
== NULL
)
7937 if (pfn_freeaddrinfo
)
7938 pfn_freeaddrinfo (ai
);
7941 eassert (ai
->ai_next
== NULL
);
7947 sys_shutdown (int s
, int how
)
7949 if (winsock_lib
== NULL
)
7952 return SOCKET_ERROR
;
7956 if (fd_info
[s
].flags
& FILE_SOCKET
)
7958 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7959 if (rc
== SOCKET_ERROR
)
7964 return SOCKET_ERROR
;
7968 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7970 if (winsock_lib
== NULL
)
7973 return SOCKET_ERROR
;
7977 if (fd_info
[s
].flags
& FILE_SOCKET
)
7979 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7980 (const char *)optval
, optlen
);
7981 if (rc
== SOCKET_ERROR
)
7986 return SOCKET_ERROR
;
7990 sys_listen (int s
, int backlog
)
7992 if (winsock_lib
== NULL
)
7995 return SOCKET_ERROR
;
7999 if (fd_info
[s
].flags
& FILE_SOCKET
)
8001 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
8002 if (rc
== SOCKET_ERROR
)
8005 fd_info
[s
].flags
|= FILE_LISTEN
;
8009 return SOCKET_ERROR
;
8013 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
8015 if (winsock_lib
== NULL
)
8018 return SOCKET_ERROR
;
8022 if (fd_info
[s
].flags
& FILE_SOCKET
)
8024 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
8025 if (rc
== SOCKET_ERROR
)
8030 return SOCKET_ERROR
;
8034 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
8036 if (winsock_lib
== NULL
)
8043 if (fd_info
[s
].flags
& FILE_LISTEN
)
8045 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
8047 if (t
== INVALID_SOCKET
)
8050 fd
= socket_to_fd (t
);
8054 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8055 ResetEvent (fd_info
[s
].cp
->char_avail
);
8064 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
8065 struct sockaddr
* from
, int * fromlen
)
8067 if (winsock_lib
== NULL
)
8070 return SOCKET_ERROR
;
8074 if (fd_info
[s
].flags
& FILE_SOCKET
)
8076 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
8077 if (rc
== SOCKET_ERROR
)
8082 return SOCKET_ERROR
;
8086 sys_sendto (int s
, const char * buf
, int len
, int flags
,
8087 const struct sockaddr
* to
, int tolen
)
8089 if (winsock_lib
== NULL
)
8092 return SOCKET_ERROR
;
8096 if (fd_info
[s
].flags
& FILE_SOCKET
)
8098 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
8099 if (rc
== SOCKET_ERROR
)
8104 return SOCKET_ERROR
;
8107 /* Windows does not have an fcntl function. Provide an implementation
8108 good enough for Emacs. */
8110 fcntl (int s
, int cmd
, int options
)
8112 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8113 invoked in a context where fd1 is closed and all descriptors less
8114 than fd1 are open, so sys_dup is an adequate implementation. */
8115 if (cmd
== F_DUPFD_CLOEXEC
)
8119 if (fd_info
[s
].flags
& FILE_SOCKET
)
8121 if (winsock_lib
== NULL
)
8127 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8129 unsigned long nblock
= 1;
8130 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
8131 if (rc
== SOCKET_ERROR
)
8133 /* Keep track of the fact that we set this to non-blocking. */
8134 fd_info
[s
].flags
|= FILE_NDELAY
;
8140 return SOCKET_ERROR
;
8143 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
8144 == (FILE_PIPE
| FILE_WRITE
))
8146 /* Force our writes to pipes be non-blocking. */
8147 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8149 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
8150 DWORD pipe_mode
= PIPE_NOWAIT
;
8152 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
8154 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8155 return SOCKET_ERROR
;
8157 fd_info
[s
].flags
|= FILE_NDELAY
;
8163 return SOCKET_ERROR
;
8167 return SOCKET_ERROR
;
8171 /* Shadow main io functions: we need to handle pipes and sockets more
8185 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
8187 child_process
* cp
= fd_info
[fd
].cp
;
8189 fd_info
[fd
].cp
= NULL
;
8191 if (CHILD_ACTIVE (cp
))
8193 /* if last descriptor to active child_process then cleanup */
8195 for (i
= 0; i
< MAXDESC
; i
++)
8199 if (fd_info
[i
].cp
== cp
)
8204 if (fd_info
[fd
].flags
& FILE_SOCKET
)
8206 if (winsock_lib
== NULL
) emacs_abort ();
8208 pfn_shutdown (SOCK_HANDLE (fd
), 2);
8209 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
8211 winsock_inuse
--; /* count open sockets */
8213 /* If the process handle is NULL, it's either a socket
8214 or serial connection, or a subprocess that was
8215 already reaped by reap_subprocess, but whose
8216 resources were not yet freed, because its output was
8217 not fully read yet by the time it was reaped. (This
8218 usually happens with async subprocesses whose output
8219 is being read by Emacs.) Otherwise, this process was
8220 not reaped yet, so we set its FD to a negative value
8221 to make sure sys_select will eventually get to
8222 calling the SIGCHLD handler for it, which will then
8223 invoke waitpid and reap_subprocess. */
8224 if (cp
->procinfo
.hProcess
== NULL
)
8232 if (fd
>= 0 && fd
< MAXDESC
)
8233 fd_info
[fd
].flags
= 0;
8235 /* Note that sockets do not need special treatment here (at least on
8236 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8237 closesocket is equivalent to CloseHandle, which is to be expected
8238 because socket handles are fully fledged kernel handles. */
8250 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8252 /* duplicate our internal info as well */
8253 fd_info
[new_fd
] = fd_info
[fd
];
8259 sys_dup2 (int src
, int dst
)
8263 if (dst
< 0 || dst
>= MAXDESC
)
8269 /* MS _dup2 seems to have weird side effect when invoked with 2
8270 identical arguments: an attempt to fclose the corresponding stdio
8271 stream after that hangs (we do close standard streams in
8272 init_ntproc). Attempt to avoid that by not calling _dup2 that
8273 way: if SRC is valid, we know that dup2 should be a no-op, so do
8274 nothing and return DST. */
8277 if ((HANDLE
)_get_osfhandle (src
) == INVALID_HANDLE_VALUE
)
8285 /* Make sure we close the destination first if it's a pipe or socket. */
8286 if (fd_info
[dst
].flags
!= 0)
8289 rc
= _dup2 (src
, dst
);
8292 /* Duplicate our internal info as well. */
8293 fd_info
[dst
] = fd_info
[src
];
8295 return rc
== 0 ? dst
: rc
;
8299 pipe2 (int * phandles
, int pipe2_flags
)
8303 unsigned pipe_size
= 0;
8305 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8307 /* Allow Lisp to override the default buffer size of the pipe. */
8308 if (w32_pipe_buffer_size
> 0 && w32_pipe_buffer_size
< UINT_MAX
)
8309 pipe_size
= w32_pipe_buffer_size
;
8311 /* make pipe handles non-inheritable; when we spawn a child, we
8312 replace the relevant handle with an inheritable one. Also put
8313 pipes into binary mode; we will do text mode translation ourselves
8315 rc
= _pipe (phandles
, pipe_size
, _O_NOINHERIT
| _O_BINARY
);
8319 /* Protect against overflow, since Windows can open more handles than
8320 our fd_info array has room for. */
8321 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8323 _close (phandles
[0]);
8324 _close (phandles
[1]);
8330 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8331 fd_info
[phandles
[0]].flags
= flags
;
8333 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8334 fd_info
[phandles
[1]].flags
= flags
;
8341 /* Function to do blocking read of one byte, needed to implement
8342 select. It is only allowed on communication ports, sockets, or
8345 _sys_read_ahead (int fd
)
8350 if (fd
< 0 || fd
>= MAXDESC
)
8351 return STATUS_READ_ERROR
;
8353 cp
= fd_info
[fd
].cp
;
8355 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8356 return STATUS_READ_ERROR
;
8358 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8359 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8361 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8365 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8366 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8367 cp
->status
= STATUS_READ_IN_PROGRESS
;
8369 if (fd_info
[fd
].flags
& FILE_PIPE
)
8371 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8373 /* Give subprocess time to buffer some more output for us before
8374 reporting that input is available; we need this because Windows 95
8375 connects DOS programs to pipes by making the pipe appear to be
8376 the normal console stdout - as a result most DOS programs will
8377 write to stdout without buffering, ie. one character at a
8378 time. Even some W32 programs do this - "dir" in a command
8379 shell on NT is very slow if we don't do this. */
8382 int wait
= w32_pipe_read_delay
;
8388 /* Yield remainder of our time slice, effectively giving a
8389 temporary priority boost to the child process. */
8393 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8395 HANDLE hnd
= fd_info
[fd
].hnd
;
8396 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8399 /* Configure timeouts for blocking read. */
8400 if (!GetCommTimeouts (hnd
, &ct
))
8402 cp
->status
= STATUS_READ_ERROR
;
8403 return STATUS_READ_ERROR
;
8405 ct
.ReadIntervalTimeout
= 0;
8406 ct
.ReadTotalTimeoutMultiplier
= 0;
8407 ct
.ReadTotalTimeoutConstant
= 0;
8408 if (!SetCommTimeouts (hnd
, &ct
))
8410 cp
->status
= STATUS_READ_ERROR
;
8411 return STATUS_READ_ERROR
;
8414 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8416 if (GetLastError () != ERROR_IO_PENDING
)
8418 cp
->status
= STATUS_READ_ERROR
;
8419 return STATUS_READ_ERROR
;
8421 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8423 cp
->status
= STATUS_READ_ERROR
;
8424 return STATUS_READ_ERROR
;
8428 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8430 unsigned long nblock
= 0;
8431 /* We always want this to block, so temporarily disable NDELAY. */
8432 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8433 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8435 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8437 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8440 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8444 if (rc
== sizeof (char))
8445 cp
->status
= STATUS_READ_SUCCEEDED
;
8447 cp
->status
= STATUS_READ_FAILED
;
8453 _sys_wait_accept (int fd
)
8459 if (fd
< 0 || fd
>= MAXDESC
)
8460 return STATUS_READ_ERROR
;
8462 cp
= fd_info
[fd
].cp
;
8464 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8465 return STATUS_READ_ERROR
;
8467 cp
->status
= STATUS_READ_FAILED
;
8469 hEv
= pfn_WSACreateEvent ();
8470 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8471 if (rc
!= SOCKET_ERROR
)
8474 rc
= WaitForSingleObject (hEv
, 500);
8476 } while (rc
== WAIT_TIMEOUT
8477 && cp
->status
!= STATUS_READ_ERROR
8479 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8480 if (rc
== WAIT_OBJECT_0
)
8481 cp
->status
= STATUS_READ_SUCCEEDED
;
8483 pfn_WSACloseEvent (hEv
);
8489 _sys_wait_connect (int fd
)
8495 if (fd
< 0 || fd
>= MAXDESC
)
8496 return STATUS_READ_ERROR
;
8498 cp
= fd_info
[fd
].cp
;
8499 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8500 return STATUS_READ_ERROR
;
8502 cp
->status
= STATUS_READ_FAILED
;
8504 hEv
= pfn_WSACreateEvent ();
8505 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8506 if (rc
!= SOCKET_ERROR
)
8509 rc
= WaitForSingleObject (hEv
, 500);
8511 } while (rc
== WAIT_TIMEOUT
8512 && cp
->status
!= STATUS_READ_ERROR
8514 if (rc
== WAIT_OBJECT_0
)
8516 /* We've got an event, but it could be a successful
8517 connection, or it could be a failure. Find out
8519 WSANETWORKEVENTS events
;
8521 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8522 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8523 && events
.iErrorCode
[FD_CONNECT_BIT
])
8525 cp
->status
= STATUS_CONNECT_FAILED
;
8526 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8530 cp
->status
= STATUS_READ_SUCCEEDED
;
8534 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8537 pfn_WSACloseEvent (hEv
);
8543 sys_read (int fd
, char * buffer
, unsigned int count
)
8548 char * orig_buffer
= buffer
;
8556 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8558 child_process
*cp
= fd_info
[fd
].cp
;
8560 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8568 /* re-read CR carried over from last read */
8569 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8571 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8575 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8578 /* presence of a child_process structure means we are operating in
8579 non-blocking mode - otherwise we just call _read directly.
8580 Note that the child_process structure might be missing because
8581 reap_subprocess has been called; in this case the pipe is
8582 already broken, so calling _read on it is okay. */
8585 int current_status
= cp
->status
;
8587 switch (current_status
)
8589 case STATUS_READ_FAILED
:
8590 case STATUS_READ_ERROR
:
8591 /* report normal EOF if nothing in buffer */
8593 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8596 case STATUS_READ_READY
:
8597 case STATUS_READ_IN_PROGRESS
:
8599 /* This happens all the time during GnuTLS handshake
8600 with the remote, evidently because GnuTLS waits for
8601 the read to complete by retrying the read operation
8602 upon EAGAIN. So I'm disabling the DebPrint to avoid
8603 wasting cycles on something that is not a real
8604 problem. Enable if you need to debug something that
8606 DebPrint (("sys_read called when read is in progress %d\n",
8609 errno
= EWOULDBLOCK
;
8612 case STATUS_READ_SUCCEEDED
:
8613 /* consume read-ahead char */
8614 *buffer
++ = cp
->chr
;
8617 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8618 ResetEvent (cp
->char_avail
);
8620 case STATUS_READ_ACKNOWLEDGED
:
8621 case STATUS_CONNECT_FAILED
:
8625 DebPrint (("sys_read: bad status %d\n", current_status
));
8630 if (fd_info
[fd
].flags
& FILE_PIPE
)
8632 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8633 to_read
= min (waiting
, (DWORD
) count
);
8636 nchars
+= _read (fd
, buffer
, to_read
);
8638 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8640 HANDLE hnd
= fd_info
[fd
].hnd
;
8641 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8647 /* Configure timeouts for non-blocking read. */
8648 if (!GetCommTimeouts (hnd
, &ct
))
8653 ct
.ReadIntervalTimeout
= MAXDWORD
;
8654 ct
.ReadTotalTimeoutMultiplier
= 0;
8655 ct
.ReadTotalTimeoutConstant
= 0;
8656 if (!SetCommTimeouts (hnd
, &ct
))
8662 if (!ResetEvent (ovl
->hEvent
))
8667 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8669 if (GetLastError () != ERROR_IO_PENDING
)
8674 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8683 else /* FILE_SOCKET */
8685 if (winsock_lib
== NULL
) emacs_abort ();
8687 /* When a non-blocking 'connect' call fails,
8688 wait_reading_process_output detects this by calling
8689 'getpeername', and then attempts to obtain the connection
8690 error code by trying to read 1 byte from the socket. If
8691 we try to serve that read by calling 'recv' below, the
8692 error we get is a generic WSAENOTCONN, not the actual
8693 connection error. So instead, we use the actual error
8694 code stashed by '_sys_wait_connect' in cp->errcode.
8695 Alternatively, we could have used 'getsockopt', like on
8696 GNU/Linux, but: (a) I have no idea whether the winsock
8697 version could hang, as it does "on some systems" (see the
8698 comment in process.c); and (b) 'getsockopt' on Windows is
8699 documented to clear the socket error for the entire
8700 process, which I'm not sure is TRT; FIXME. */
8701 if (current_status
== STATUS_CONNECT_FAILED
8702 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8703 && cp
->errcode
!= 0)
8705 pfn_WSASetLastError (cp
->errcode
);
8709 /* Do the equivalent of a non-blocking read. */
8710 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8711 if (waiting
== 0 && nchars
== 0)
8713 errno
= EWOULDBLOCK
;
8719 /* always use binary mode for sockets */
8720 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8721 if (res
== SOCKET_ERROR
)
8724 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8725 errno
, SOCK_HANDLE (fd
)));
8734 int nread
= _read (fd
, buffer
, count
);
8737 else if (nchars
== 0)
8742 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8743 /* Perform text mode translation if required. */
8744 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8746 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8747 /* If buffer contains only CR, return that. To be absolutely
8748 sure we should attempt to read the next char, but in
8749 practice a CR to be followed by LF would not appear by
8750 itself in the buffer. */
8751 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8753 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8759 nchars
= _read (fd
, buffer
, count
);
8764 /* From w32xfns.c */
8765 extern HANDLE interrupt_handle
;
8768 sys_write (int fd
, const void * buffer
, unsigned int count
)
8779 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8781 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8787 /* Perform text mode translation if required. */
8788 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8791 const unsigned char * src
= buffer
;
8792 unsigned char * dst
;
8795 SAFE_NALLOCA (tmpbuf
, 2, count
);
8796 dst
= (unsigned char *)tmpbuf
;
8800 unsigned char *next
;
8801 /* Copy next line or remaining bytes. */
8802 next
= _memccpy (dst
, src
, '\n', nbytes
);
8805 /* Copied one line ending with '\n'. */
8806 int copied
= next
- dst
;
8809 /* Insert '\r' before '\n'. */
8816 /* Copied remaining partial line -> now finished. */
8823 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8825 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8826 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8827 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8830 /* This is async (a.k.a. "overlapped") I/O, so the return value
8831 of FALSE from WriteFile means either an error or the output
8832 will be completed asynchronously (ERROR_IO_PENDING). */
8833 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8835 if (GetLastError () != ERROR_IO_PENDING
)
8842 /* Wait for the write to complete, and watch C-g while
8844 if (detect_input_pending ())
8845 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8846 INFINITE
, QS_ALLINPUT
);
8848 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8852 /* User pressed C-g, cancel write, then leave.
8853 Don't bother cleaning up as we may only get stuck
8854 in buggy drivers. */
8855 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8857 errno
= EIO
; /* Why not EINTR? */
8860 case WAIT_OBJECT_0
+ 1:
8861 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8871 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8873 unsigned long nblock
= 0;
8874 if (winsock_lib
== NULL
) emacs_abort ();
8876 child_process
*cp
= fd_info
[fd
].cp
;
8878 /* If this is a non-blocking socket whose connection is in
8879 progress or terminated with an error already, return the
8880 proper error code to the caller. */
8881 if (cp
!= NULL
&& (fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8883 /* In case connection is in progress, ENOTCONN that would
8884 result from calling pfn_send is not what callers expect. */
8885 if (cp
->status
!= STATUS_CONNECT_FAILED
)
8887 errno
= EWOULDBLOCK
;
8890 /* In case connection failed, use the actual error code
8891 stashed by '_sys_wait_connect' in cp->errcode. */
8892 else if (cp
->errcode
!= 0)
8894 pfn_WSASetLastError (cp
->errcode
);
8900 /* TODO: implement select() properly so non-blocking I/O works. */
8901 /* For now, make sure the write blocks. */
8902 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8903 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8905 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8907 if (nchars
== SOCKET_ERROR
)
8910 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8911 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8914 /* Set the socket back to non-blocking if it was before,
8915 for other operations that support it. */
8916 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8919 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8924 /* Some networked filesystems don't like too large writes, so
8925 break them into smaller chunks. See the Comments section of
8926 the MSDN documentation of WriteFile for details behind the
8927 choice of the value of CHUNK below. See also the thread
8928 http://thread.gmane.org/gmane.comp.version-control.git/145294
8929 in the git mailing list. */
8930 const unsigned char *p
= buffer
;
8931 const bool is_pipe
= (fd
< MAXDESC
8932 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8933 == (FILE_PIPE
| FILE_NDELAY
)));
8934 /* Some programs, notably Node.js's node.exe, seem to never
8935 completely empty the pipe, so writing more than the size of
8936 the pipe's buffer always returns ENOSPC, and we loop forever
8937 between send_process and here. As a workaround, write no
8938 more than the pipe's buffer can hold. */
8939 DWORD pipe_buffer_size
;
8942 if (!GetNamedPipeInfo ((HANDLE
)_get_osfhandle (fd
),
8943 NULL
, &pipe_buffer_size
, NULL
, NULL
))
8945 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8946 pipe_buffer_size
= 4096;
8949 const unsigned chunk
= is_pipe
? pipe_buffer_size
: 30 * 1024 * 1024;
8955 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8956 int n
= _write (fd
, p
, this_chunk
);
8962 /* When there's no buffer space in a pipe that is in the
8963 non-blocking mode, _write returns ENOSPC. We return
8964 EAGAIN instead, which should trigger the logic in
8965 send_process that enters waiting loop and calls
8966 wait_reading_process_output to allow process input to
8967 be accepted during the wait. Those calls to
8968 wait_reading_process_output allow sys_select to
8969 notice when process input becomes available, thus
8970 avoiding deadlock whereby each side of the pipe is
8971 blocked on write, waiting for the other party to read
8972 its end of the pipe. */
8973 if (errno
== ENOSPC
&& is_pipe
)
8979 else if (n
< this_chunk
)
8991 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8993 /* Return information about network interface IFNAME, or about all
8994 interfaces (if IFNAME is nil). */
8996 network_interface_get_info (Lisp_Object ifname
)
8998 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8999 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
9000 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
9001 Lisp_Object res
= Qnil
;
9003 if (retval
== ERROR_BUFFER_OVERFLOW
)
9005 ainfo
= xrealloc (ainfo
, ainfo_len
);
9006 retval
= get_adapters_info (ainfo
, &ainfo_len
);
9009 if (retval
== ERROR_SUCCESS
)
9011 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
9012 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
9014 struct sockaddr_in sa
;
9016 /* For the below, we need some winsock functions, so make sure
9017 the winsock DLL is loaded. If we cannot successfully load
9018 it, they will have no use of the information we provide,
9020 if (!winsock_lib
&& !init_winsock (1))
9023 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
9025 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
9027 /* Present Unix-compatible interface names, instead of the
9028 Windows names, which are really GUIDs not readable by
9030 static const char *ifmt
[] = {
9031 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9046 switch (adapter
->Type
)
9048 case MIB_IF_TYPE_ETHERNET
:
9049 /* Windows before Vista reports wireless adapters as
9050 Ethernet. Work around by looking at the Description
9052 if (strstr (adapter
->Description
, "Wireless "))
9055 if_num
= wlan_count
++;
9059 ifmt_idx
= ETHERNET
;
9060 if_num
= eth_count
++;
9063 case MIB_IF_TYPE_TOKENRING
:
9064 ifmt_idx
= TOKENRING
;
9065 if_num
= tr_count
++;
9067 case MIB_IF_TYPE_FDDI
:
9069 if_num
= fddi_count
++;
9071 case MIB_IF_TYPE_PPP
:
9073 if_num
= ppp_count
++;
9075 case MIB_IF_TYPE_SLIP
:
9077 if_num
= sl_count
++;
9079 case IF_TYPE_IEEE80211
:
9081 if_num
= wlan_count
++;
9083 case MIB_IF_TYPE_LOOPBACK
:
9086 ifmt_idx
= LOOPBACK
;
9087 if_num
= lo_count
++;
9093 ifmt_idx
= OTHER_IF
;
9094 if_num
= ifx_count
++;
9097 if (ifmt_idx
== NONE
)
9099 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
9101 sa
.sin_family
= AF_INET
;
9102 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
9103 if (ip_addr
== INADDR_NONE
)
9105 /* Bogus address, skip this interface. */
9108 sa
.sin_addr
.s_addr
= ip_addr
;
9111 res
= Fcons (Fcons (build_string (namebuf
),
9112 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9113 sizeof (struct sockaddr
))),
9115 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
9117 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
9118 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
9119 Lisp_Object flags
= Qnil
;
9123 /* Flags. We guess most of them by type, since the
9124 Windows flags are different and hard to get by. */
9125 flags
= Fcons (intern ("up"), flags
);
9126 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
9128 flags
= Fcons (intern ("broadcast"), flags
);
9129 flags
= Fcons (intern ("multicast"), flags
);
9131 flags
= Fcons (intern ("running"), flags
);
9132 if (ifmt_idx
== PPP
)
9134 flags
= Fcons (intern ("pointopoint"), flags
);
9135 flags
= Fcons (intern ("noarp"), flags
);
9137 if (adapter
->HaveWins
)
9138 flags
= Fcons (intern ("WINS"), flags
);
9139 if (adapter
->DhcpEnabled
)
9140 flags
= Fcons (intern ("dynamic"), flags
);
9142 res
= Fcons (flags
, res
);
9144 /* Hardware address and its family. */
9145 for (n
= 0; n
< adapter
->AddressLength
; n
++)
9146 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
9147 /* Windows does not support AF_LINK or AF_PACKET family
9148 of addresses. Use an arbitrary family number that is
9149 identical to what GNU/Linux returns. */
9150 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
9153 sa
.sin_family
= AF_INET
;
9154 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
9155 if (net_mask
!= INADDR_NONE
)
9157 sa
.sin_addr
.s_addr
= net_mask
;
9159 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9160 sizeof (struct sockaddr
)),
9164 res
= Fcons (Qnil
, res
);
9166 sa
.sin_family
= AF_INET
;
9167 if (ip_addr
!= INADDR_NONE
)
9169 /* Broadcast address is only reported by
9170 GetAdaptersAddresses, which is of limited
9171 availability. Generate it on our own. */
9172 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
9174 sa
.sin_addr
.s_addr
= bcast_addr
;
9176 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9177 sizeof (struct sockaddr
)),
9181 sa
.sin_addr
.s_addr
= ip_addr
;
9183 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9184 sizeof (struct sockaddr
)),
9188 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
9191 /* GetAdaptersInfo is documented to not report loopback
9192 interfaces, so we generate one out of thin air. */
9195 sa
.sin_family
= AF_INET
;
9199 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9200 res
= Fcons (Fcons (build_string ("lo"),
9201 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9202 sizeof (struct sockaddr
))),
9205 else if (strcmp (SSDATA (ifname
), "lo") == 0)
9207 res
= Fcons (Fcons (intern ("running"),
9208 Fcons (intern ("loopback"),
9209 Fcons (intern ("up"), Qnil
))), Qnil
);
9210 /* 772 is what 3 different GNU/Linux systems report for
9211 the loopback interface. */
9212 res
= Fcons (Fcons (make_number (772),
9213 Fmake_vector (make_number (6),
9216 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
9217 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9218 sizeof (struct sockaddr
)),
9220 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
9221 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9222 sizeof (struct sockaddr
)),
9224 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9225 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9226 sizeof (struct sockaddr
)),
9239 network_interface_list (void)
9241 return network_interface_get_info (Qnil
);
9245 network_interface_info (Lisp_Object ifname
)
9247 CHECK_STRING (ifname
);
9248 return network_interface_get_info (ifname
);
9252 /* The Windows CRT functions are "optimized for speed", so they don't
9253 check for timezone and DST changes if they were last called less
9254 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9255 all Emacs features that repeatedly call time functions (e.g.,
9256 display-time) are in real danger of missing timezone and DST
9257 changes. Calling tzset before each localtime call fixes that. */
9259 sys_localtime (const time_t *t
)
9262 return localtime (t
);
9267 /* Try loading LIBRARY_ID from the file(s) specified in
9268 Vdynamic_library_alist. If the library is loaded successfully,
9269 return the handle of the DLL, and record the filename in the
9270 property :loaded-from of LIBRARY_ID. If the library could not be
9271 found, or when it was already loaded (because the handle is not
9272 recorded anywhere, and so is lost after use), return NULL.
9274 We could also save the handle in :loaded-from, but currently
9275 there's no use case for it. */
9277 w32_delayed_load (Lisp_Object library_id
)
9279 HMODULE dll_handle
= NULL
;
9281 CHECK_SYMBOL (library_id
);
9283 if (CONSP (Vdynamic_library_alist
)
9284 && NILP (Fassq (library_id
, Vlibrary_cache
)))
9286 Lisp_Object found
= Qnil
;
9287 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
9290 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
9292 Lisp_Object dll
= XCAR (dlls
);
9293 char name
[MAX_UTF8_PATH
];
9297 dll
= ENCODE_FILE (dll
);
9298 if (w32_unicode_filenames
)
9300 wchar_t name_w
[MAX_PATH
];
9302 filename_to_utf16 (SSDATA (dll
), name_w
);
9303 dll_handle
= LoadLibraryW (name_w
);
9306 res
= GetModuleFileNameW (dll_handle
, name_w
,
9309 filename_from_utf16 (name_w
, name
);
9314 char name_a
[MAX_PATH
];
9316 filename_to_ansi (SSDATA (dll
), name_a
);
9317 dll_handle
= LoadLibraryA (name_a
);
9320 res
= GetModuleFileNameA (dll_handle
, name_a
,
9323 filename_from_ansi (name_a
, name
);
9328 ptrdiff_t len
= strlen (name
);
9331 /* Possibly truncated */
9332 ? make_specified_string (name
, -1, len
, 1)
9334 /* This prevents thread start and end notifications
9335 from being sent to the DLL, for every thread we
9336 start. We don't need those notifications because
9337 threads we create never use any of these DLLs, only
9338 the main thread uses them. This is supposed to
9339 speed up thread creation. */
9340 DisableThreadLibraryCalls (dll_handle
);
9345 Fput (library_id
, QCloaded_from
, found
);
9353 check_windows_init_file (void)
9355 /* A common indication that Emacs is not installed properly is when
9356 it cannot find the Windows installation file. If this file does
9357 not exist in the expected place, tell the user. */
9359 if (!noninteractive
&& !inhibit_window_system
9360 /* Vload_path is not yet initialized when we are loading
9362 && NILP (Vpurify_flag
))
9364 Lisp_Object init_file
;
9367 /* Implementation note: this function runs early during Emacs
9368 startup, before startup.el is run. So Vload_path is still in
9369 its initial unibyte form, but it holds UTF-8 encoded file
9370 names, since init_callproc was already called. So we do not
9371 need to ENCODE_FILE here, but we do need to convert the file
9372 names from UTF-8 to ANSI. */
9373 init_file
= build_string ("term/w32-win");
9374 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9377 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9378 char *init_file_name
= SSDATA (init_file
);
9379 char *load_path
= SSDATA (load_path_print
);
9380 char *buffer
= alloca (1024
9381 + strlen (init_file_name
)
9382 + strlen (load_path
));
9387 "The Emacs Windows initialization file \"%s.el\" "
9388 "could not be found in your Emacs installation. "
9389 "Emacs checked the following directories for this file:\n"
9391 "When Emacs cannot find this file, it usually means that it "
9392 "was not installed properly, or its distribution file was "
9393 "not unpacked properly.\nSee the README.W32 file in the "
9394 "top-level Emacs directory for more information.",
9395 init_file_name
, load_path
);
9396 needed
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
,
9397 buffer
, -1, NULL
, 0);
9400 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9402 pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, buffer
,
9404 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9405 NULL
, 0, NULL
, NULL
);
9408 char *msg_a
= alloca (needed
+ 1);
9410 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9417 "Emacs Abort Dialog",
9418 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9419 /* Use the low-level system abort. */
9430 term_ntproc (int ignored
)
9436 /* shutdown the socket interface if necessary */
9443 init_ntproc (int dumping
)
9445 sigset_t initial_mask
= 0;
9447 /* Initialize the socket interface now if available and requested by
9448 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9449 delayed until open-network-stream is called (w32-has-winsock can
9450 also be used to dynamically load or reload winsock).
9452 Conveniently, init_environment is called before us, so
9453 PRELOAD_WINSOCK can be set in the registry. */
9455 /* Always initialize this correctly. */
9458 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9459 init_winsock (TRUE
);
9461 /* Initial preparation for subprocess support: replace our standard
9462 handles with non-inheritable versions. */
9465 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9466 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9467 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9469 parent
= GetCurrentProcess ();
9471 /* ignore errors when duplicating and closing; typically the
9472 handles will be invalid when running as a gui program. */
9473 DuplicateHandle (parent
,
9474 GetStdHandle (STD_INPUT_HANDLE
),
9479 DUPLICATE_SAME_ACCESS
);
9481 DuplicateHandle (parent
,
9482 GetStdHandle (STD_OUTPUT_HANDLE
),
9487 DUPLICATE_SAME_ACCESS
);
9489 DuplicateHandle (parent
,
9490 GetStdHandle (STD_ERROR_HANDLE
),
9495 DUPLICATE_SAME_ACCESS
);
9501 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9502 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9504 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9507 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9508 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9510 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9513 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9514 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9516 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9520 /* unfortunately, atexit depends on implementation of malloc */
9521 /* atexit (term_ntproc); */
9524 /* Make sure we start with all signals unblocked. */
9525 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9526 signal (SIGABRT
, term_ntproc
);
9530 /* determine which drives are fixed, for GetCachedVolumeInformation */
9532 /* GetDriveType must have trailing backslash. */
9533 char drive
[] = "A:\\";
9535 /* Loop over all possible drive letters */
9536 while (*drive
<= 'Z')
9538 /* Record if this drive letter refers to a fixed drive. */
9539 fixed_drives
[DRIVE_INDEX (*drive
)] =
9540 (GetDriveType (drive
) == DRIVE_FIXED
);
9545 /* Reset the volume info cache. */
9546 volume_cache
= NULL
;
9551 shutdown_handler ensures that buffers' autosave files are
9552 up to date when the user logs off, or the system shuts down.
9555 shutdown_handler (DWORD type
)
9557 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9558 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9559 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9560 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9562 /* Shut down cleanly, making sure autosave files are up to date. */
9563 shut_down_emacs (0, Qnil
);
9566 /* Allow other handlers to handle this signal. */
9570 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9571 NT, return a handle to GDI32.DLL. */
9573 maybe_load_unicows_dll (void)
9575 if (os_subtype
== OS_9X
)
9577 HANDLE ret
= LoadLibrary ("Unicows.dll");
9580 /* These two functions are present on Windows 9X as stubs
9581 that always fail. We need the real implementations from
9582 UNICOWS.DLL, so we must call these functions through
9583 pointers, and assign the correct addresses to these
9584 pointers at program startup (see emacs.c, which calls
9585 this function early on). */
9586 pMultiByteToWideChar
=
9587 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9588 pWideCharToMultiByte
=
9589 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9590 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9597 button
= MessageBox (NULL
,
9598 "Emacs cannot load the UNICOWS.DLL library.\n"
9599 "This library is essential for using Emacs\n"
9600 "on this system. You need to install it.\n\n"
9601 "Emacs will exit when you click OK.",
9602 "Emacs cannot load UNICOWS.DLL",
9603 MB_ICONERROR
| MB_TASKMODAL
9604 | MB_SETFOREGROUND
| MB_OK
);
9615 /* On NT family of Windows, these two functions are always
9616 linked in, so we just assign their addresses to the 2
9617 pointers; no need for the LoadLibrary dance. */
9618 pMultiByteToWideChar
= MultiByteToWideChar
;
9619 pWideCharToMultiByte
= WideCharToMultiByte
;
9620 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9621 if (w32_major_version
< 5)
9622 multiByteToWideCharFlags
= 0;
9624 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9625 return LoadLibrary ("Gdi32.dll");
9630 globals_of_w32 is used to initialize those global variables that
9631 must always be initialized on startup even when the global variable
9632 initialized is non zero (see the function main in emacs.c).
9635 globals_of_w32 (void)
9637 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9639 get_process_times_fn
= (GetProcessTimes_Proc
)
9640 GetProcAddress (kernel32
, "GetProcessTimes");
9642 DEFSYM (QCloaded_from
, ":loaded-from");
9644 g_b_init_is_windows_9x
= 0;
9645 g_b_init_open_process_token
= 0;
9646 g_b_init_get_token_information
= 0;
9647 g_b_init_lookup_account_sid
= 0;
9648 g_b_init_get_sid_sub_authority
= 0;
9649 g_b_init_get_sid_sub_authority_count
= 0;
9650 g_b_init_get_security_info
= 0;
9651 g_b_init_get_file_security_w
= 0;
9652 g_b_init_get_file_security_a
= 0;
9653 g_b_init_get_security_descriptor_owner
= 0;
9654 g_b_init_get_security_descriptor_group
= 0;
9655 g_b_init_is_valid_sid
= 0;
9656 g_b_init_create_toolhelp32_snapshot
= 0;
9657 g_b_init_process32_first
= 0;
9658 g_b_init_process32_next
= 0;
9659 g_b_init_open_thread_token
= 0;
9660 g_b_init_impersonate_self
= 0;
9661 g_b_init_revert_to_self
= 0;
9662 g_b_init_get_process_memory_info
= 0;
9663 g_b_init_get_process_working_set_size
= 0;
9664 g_b_init_global_memory_status
= 0;
9665 g_b_init_global_memory_status_ex
= 0;
9666 g_b_init_equal_sid
= 0;
9667 g_b_init_copy_sid
= 0;
9668 g_b_init_get_length_sid
= 0;
9669 g_b_init_get_native_system_info
= 0;
9670 g_b_init_get_system_times
= 0;
9671 g_b_init_create_symbolic_link_w
= 0;
9672 g_b_init_create_symbolic_link_a
= 0;
9673 g_b_init_get_security_descriptor_dacl
= 0;
9674 g_b_init_convert_sd_to_sddl
= 0;
9675 g_b_init_convert_sddl_to_sd
= 0;
9676 g_b_init_is_valid_security_descriptor
= 0;
9677 g_b_init_set_file_security_w
= 0;
9678 g_b_init_set_file_security_a
= 0;
9679 g_b_init_set_named_security_info_w
= 0;
9680 g_b_init_set_named_security_info_a
= 0;
9681 g_b_init_get_adapters_info
= 0;
9682 g_b_init_compare_string_w
= 0;
9683 g_b_init_debug_break_process
= 0;
9684 num_of_processors
= 0;
9685 /* The following sets a handler for shutdown notifications for
9686 console apps. This actually applies to Emacs in both console and
9687 GUI modes, since we had to fool windows into thinking emacs is a
9688 console application to get console mode to work. */
9689 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9691 /* "None" is the default group name on standalone workstations. */
9692 strcpy (dflt_group_name
, "None");
9694 /* Reset, in case it has some value inherited from dump time. */
9695 w32_stat_get_owner_group
= 0;
9697 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9698 (a.k.a. "wide") APIs to invoke functions that accept file
9700 if (is_windows_9x ())
9701 w32_unicode_filenames
= 0;
9703 w32_unicode_filenames
= 1;
9706 dynlib_reset_last_error ();
9709 w32_crypto_hprov
= (HCRYPTPROV
)0;
9712 /* For make-serial-process */
9714 serial_open (Lisp_Object port_obj
)
9716 char *port
= SSDATA (port_obj
);
9721 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9722 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9723 if (hnd
== INVALID_HANDLE_VALUE
)
9724 error ("Could not open %s", port
);
9725 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9727 error ("Could not open %s", port
);
9731 error ("Could not create child process");
9733 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9734 fd_info
[ fd
].hnd
= hnd
;
9735 fd_info
[ fd
].flags
|=
9736 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9737 if (fd_info
[ fd
].cp
!= NULL
)
9739 error ("fd_info[fd = %d] is already in use", fd
);
9741 fd_info
[ fd
].cp
= cp
;
9742 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9743 if (cp
->ovl_read
.hEvent
== NULL
)
9744 error ("Could not create read event");
9745 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9746 if (cp
->ovl_write
.hEvent
== NULL
)
9747 error ("Could not create write event");
9752 /* For serial-process-configure */
9754 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9756 Lisp_Object childp2
= Qnil
;
9757 Lisp_Object tem
= Qnil
;
9761 char summary
[4] = "???"; /* This usually becomes "8N1". */
9763 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9764 error ("Not a serial process");
9765 hnd
= fd_info
[ p
->outfd
].hnd
;
9767 childp2
= Fcopy_sequence (p
->childp
);
9769 /* Initialize timeouts for blocking read and blocking write. */
9770 if (!GetCommTimeouts (hnd
, &ct
))
9771 error ("GetCommTimeouts() failed");
9772 ct
.ReadIntervalTimeout
= 0;
9773 ct
.ReadTotalTimeoutMultiplier
= 0;
9774 ct
.ReadTotalTimeoutConstant
= 0;
9775 ct
.WriteTotalTimeoutMultiplier
= 0;
9776 ct
.WriteTotalTimeoutConstant
= 0;
9777 if (!SetCommTimeouts (hnd
, &ct
))
9778 error ("SetCommTimeouts() failed");
9779 /* Read port attributes and prepare default configuration. */
9780 memset (&dcb
, 0, sizeof (dcb
));
9781 dcb
.DCBlength
= sizeof (DCB
);
9782 if (!GetCommState (hnd
, &dcb
))
9783 error ("GetCommState() failed");
9786 dcb
.fAbortOnError
= FALSE
;
9787 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9792 /* Configure speed. */
9793 if (!NILP (Fplist_member (contact
, QCspeed
)))
9794 tem
= Fplist_get (contact
, QCspeed
);
9796 tem
= Fplist_get (p
->childp
, QCspeed
);
9798 dcb
.BaudRate
= XINT (tem
);
9799 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9801 /* Configure bytesize. */
9802 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9803 tem
= Fplist_get (contact
, QCbytesize
);
9805 tem
= Fplist_get (p
->childp
, QCbytesize
);
9807 tem
= make_number (8);
9809 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9810 error (":bytesize must be nil (8), 7, or 8");
9811 dcb
.ByteSize
= XINT (tem
);
9812 summary
[0] = XINT (tem
) + '0';
9813 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9815 /* Configure parity. */
9816 if (!NILP (Fplist_member (contact
, QCparity
)))
9817 tem
= Fplist_get (contact
, QCparity
);
9819 tem
= Fplist_get (p
->childp
, QCparity
);
9820 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9821 error (":parity must be nil (no parity), `even', or `odd'");
9822 dcb
.fParity
= FALSE
;
9823 dcb
.Parity
= NOPARITY
;
9824 dcb
.fErrorChar
= FALSE
;
9829 else if (EQ (tem
, Qeven
))
9833 dcb
.Parity
= EVENPARITY
;
9834 dcb
.fErrorChar
= TRUE
;
9836 else if (EQ (tem
, Qodd
))
9840 dcb
.Parity
= ODDPARITY
;
9841 dcb
.fErrorChar
= TRUE
;
9843 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9845 /* Configure stopbits. */
9846 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9847 tem
= Fplist_get (contact
, QCstopbits
);
9849 tem
= Fplist_get (p
->childp
, QCstopbits
);
9851 tem
= make_number (1);
9853 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9854 error (":stopbits must be nil (1 stopbit), 1, or 2");
9855 summary
[2] = XINT (tem
) + '0';
9856 if (XINT (tem
) == 1)
9857 dcb
.StopBits
= ONESTOPBIT
;
9858 else if (XINT (tem
) == 2)
9859 dcb
.StopBits
= TWOSTOPBITS
;
9860 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9862 /* Configure flowcontrol. */
9863 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9864 tem
= Fplist_get (contact
, QCflowcontrol
);
9866 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9867 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9868 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9869 dcb
.fOutxCtsFlow
= FALSE
;
9870 dcb
.fOutxDsrFlow
= FALSE
;
9871 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9872 dcb
.fDsrSensitivity
= FALSE
;
9873 dcb
.fTXContinueOnXoff
= FALSE
;
9876 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9877 dcb
.XonChar
= 17; /* Control-Q */
9878 dcb
.XoffChar
= 19; /* Control-S */
9881 /* Already configured. */
9883 else if (EQ (tem
, Qhw
))
9885 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9886 dcb
.fOutxCtsFlow
= TRUE
;
9888 else if (EQ (tem
, Qsw
))
9893 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9895 /* Activate configuration. */
9896 if (!SetCommState (hnd
, &dcb
))
9897 error ("SetCommState() failed");
9899 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9900 pset_childp (p
, childp2
);
9903 /* For make-pipe-process */
9905 register_aux_fd (int infd
)
9911 error ("Could not create child process");
9913 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9915 if (fd_info
[ infd
].cp
!= NULL
)
9917 error ("fd_info[fd = %d] is already in use", infd
);
9919 fd_info
[ infd
].cp
= cp
;
9920 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
9926 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9929 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9930 int fd
= process
->infd
;
9932 n
= sys_read (fd
, (char*)buf
, sz
);
9939 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9940 if (err
== EWOULDBLOCK
)
9943 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9949 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9951 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9952 int fd
= process
->outfd
;
9953 ssize_t n
= sys_write (fd
, buf
, sz
);
9955 /* 0 or more bytes written means everything went fine. */
9959 /* Negative bytes written means we got an error in errno.
9960 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9961 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9962 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9966 #endif /* HAVE_GNUTLS */