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 struct timespec
*, void *);
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 /* Produce a Windows ANSI codepage suitable for encoding file names.
1513 Return the information about that codepage in CP_INFO. */
1515 codepage_for_filenames (CPINFO
*cp_info
)
1517 /* A simple cache to avoid calling GetCPInfo every time we need to
1518 encode/decode a file name. The file-name encoding is not
1519 supposed to be changed too frequently, if ever. */
1520 static Lisp_Object last_file_name_encoding
;
1522 Lisp_Object current_encoding
;
1524 current_encoding
= Vfile_name_coding_system
;
1525 if (NILP (current_encoding
))
1526 current_encoding
= Vdefault_file_name_coding_system
;
1528 if (!EQ (last_file_name_encoding
, current_encoding
))
1530 /* Default to the current ANSI codepage. */
1531 file_name_codepage
= w32_ansi_code_page
;
1533 if (NILP (current_encoding
))
1535 char *cpname
= SSDATA (SYMBOL_NAME (current_encoding
));
1536 char *cp
= NULL
, *end
;
1539 if (strncmp (cpname
, "cp", 2) == 0)
1541 else if (strncmp (cpname
, "windows-", 8) == 0)
1547 cpnum
= strtol (cp
, &end
, 10);
1548 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1549 file_name_codepage
= cpnum
;
1553 if (!file_name_codepage
)
1554 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1556 if (!GetCPInfo (file_name_codepage
, &cp
))
1558 file_name_codepage
= CP_ACP
;
1559 if (!GetCPInfo (file_name_codepage
, &cp
))
1566 return file_name_codepage
;
1570 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1572 int result
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, fn_in
,
1573 -1, fn_out
, MAX_PATH
);
1577 DWORD err
= GetLastError ();
1581 case ERROR_INVALID_FLAGS
:
1582 case ERROR_INVALID_PARAMETER
:
1585 case ERROR_INSUFFICIENT_BUFFER
:
1586 case ERROR_NO_UNICODE_TRANSLATION
:
1597 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1599 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1600 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1604 DWORD err
= GetLastError ();
1608 case ERROR_INVALID_FLAGS
:
1609 case ERROR_INVALID_PARAMETER
:
1612 case ERROR_INSUFFICIENT_BUFFER
:
1613 case ERROR_NO_UNICODE_TRANSLATION
:
1624 filename_to_ansi (const char *fn_in
, char *fn_out
)
1626 wchar_t fn_utf16
[MAX_PATH
];
1628 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1631 int codepage
= codepage_for_filenames (NULL
);
1633 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1634 fn_out
, MAX_PATH
, NULL
, NULL
);
1637 DWORD err
= GetLastError ();
1641 case ERROR_INVALID_FLAGS
:
1642 case ERROR_INVALID_PARAMETER
:
1645 case ERROR_INSUFFICIENT_BUFFER
:
1646 case ERROR_NO_UNICODE_TRANSLATION
:
1659 filename_from_ansi (const char *fn_in
, char *fn_out
)
1661 wchar_t fn_utf16
[MAX_PATH
];
1662 int codepage
= codepage_for_filenames (NULL
);
1663 int result
= pMultiByteToWideChar (codepage
, multiByteToWideCharFlags
, fn_in
,
1664 -1, fn_utf16
, MAX_PATH
);
1668 DWORD err
= GetLastError ();
1672 case ERROR_INVALID_FLAGS
:
1673 case ERROR_INVALID_PARAMETER
:
1676 case ERROR_INSUFFICIENT_BUFFER
:
1677 case ERROR_NO_UNICODE_TRANSLATION
:
1684 return filename_from_utf16 (fn_utf16
, fn_out
);
1689 /* The directory where we started, in UTF-8. */
1690 static char startup_dir
[MAX_UTF8_PATH
];
1692 /* Get the current working directory. */
1694 getcwd (char *dir
, int dirsize
)
1701 if (dirsize
<= strlen (startup_dir
))
1707 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1711 /* Emacs doesn't actually change directory itself, it stays in the
1712 same directory where it was started. */
1713 strcpy (dir
, startup_dir
);
1718 /* Emulate getloadavg. */
1720 struct load_sample
{
1727 /* Number of processors on this machine. */
1728 static unsigned num_of_processors
;
1730 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1731 static struct load_sample samples
[16*60];
1732 static int first_idx
= -1, last_idx
= -1;
1733 static int max_idx
= ARRAYELTS (samples
);
1738 int next_idx
= from
+ 1;
1740 if (next_idx
>= max_idx
)
1749 int prev_idx
= from
- 1;
1752 prev_idx
= max_idx
- 1;
1758 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1760 SYSTEM_INFO sysinfo
;
1761 FILETIME ft_idle
, ft_user
, ft_kernel
;
1763 /* Initialize the number of processors on this machine. */
1764 if (num_of_processors
<= 0)
1766 get_native_system_info (&sysinfo
);
1767 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1768 if (num_of_processors
<= 0)
1770 GetSystemInfo (&sysinfo
);
1771 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1773 if (num_of_processors
<= 0)
1774 num_of_processors
= 1;
1777 /* TODO: Take into account threads that are ready to run, by
1778 sampling the "\System\Processor Queue Length" performance
1779 counter. The code below accounts only for threads that are
1780 actually running. */
1782 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1784 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1786 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1787 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1788 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1789 *idle
= uidle
.QuadPart
;
1790 *kernel
= ukernel
.QuadPart
;
1791 *user
= uuser
.QuadPart
;
1801 /* Produce the load average for a given time interval, using the
1802 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1803 1-minute, 5-minute, or 15-minute average, respectively. */
1807 double retval
= -1.0;
1810 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1811 time_t now
= samples
[last_idx
].sample_time
;
1813 if (first_idx
!= last_idx
)
1815 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1817 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1818 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1821 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1822 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1823 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1825 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1828 if (idx
== first_idx
)
1837 getloadavg (double loadavg
[], int nelem
)
1840 ULONGLONG idle
, kernel
, user
;
1841 time_t now
= time (NULL
);
1843 /* If system time jumped back for some reason, delete all samples
1844 whose time is later than the current wall-clock time. This
1845 prevents load average figures from becoming frozen for prolonged
1846 periods of time, when system time is reset backwards. */
1849 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1851 if (last_idx
== first_idx
)
1853 first_idx
= last_idx
= -1;
1856 last_idx
= buf_prev (last_idx
);
1860 /* Store another sample. We ignore samples that are less than 1 sec
1863 || (difftime (now
, samples
[last_idx
].sample_time
)
1864 >= 1.0 - 2*DBL_EPSILON
*now
))
1866 sample_system_load (&idle
, &kernel
, &user
);
1867 last_idx
= buf_next (last_idx
);
1868 samples
[last_idx
].sample_time
= now
;
1869 samples
[last_idx
].idle
= idle
;
1870 samples
[last_idx
].kernel
= kernel
;
1871 samples
[last_idx
].user
= user
;
1872 /* If the buffer has more that 15 min worth of samples, discard
1874 if (first_idx
== -1)
1875 first_idx
= last_idx
;
1876 while (first_idx
!= last_idx
1877 && (difftime (now
, samples
[first_idx
].sample_time
)
1878 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1879 first_idx
= buf_next (first_idx
);
1882 for (elem
= 0; elem
< nelem
; elem
++)
1884 double avg
= getavg (elem
);
1888 loadavg
[elem
] = avg
;
1894 /* Emulate getpwuid, getpwnam and others. */
1896 #define PASSWD_FIELD_SIZE 256
1898 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1899 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1900 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1901 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1902 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1904 static struct passwd dflt_passwd
=
1916 static char dflt_group_name
[GNLEN
+1];
1918 static struct group dflt_group
=
1920 /* When group information is not available, we return this as the
1921 group for all files. */
1929 return dflt_passwd
.pw_uid
;
1935 /* I could imagine arguing for checking to see whether the user is
1936 in the Administrators group and returning a UID of 0 for that
1937 case, but I don't know how wise that would be in the long run. */
1944 return dflt_passwd
.pw_gid
;
1954 getpwuid (unsigned uid
)
1956 if (uid
== dflt_passwd
.pw_uid
)
1957 return &dflt_passwd
;
1962 getgrgid (gid_t gid
)
1968 getpwnam (char *name
)
1972 pw
= getpwuid (getuid ());
1976 if (xstrcasecmp (name
, pw
->pw_name
))
1983 init_user_info (void)
1985 /* Find the user's real name by opening the process token and
1986 looking up the name associated with the user-sid in that token.
1988 Use the relative portion of the identifier authority value from
1989 the user-sid as the user id value (same for group id using the
1990 primary group sid from the process token). */
1992 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1993 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1994 DWORD glength
= sizeof (gname
);
1995 HANDLE token
= NULL
;
1996 SID_NAME_USE user_type
;
1997 unsigned char *buf
= NULL
;
1999 TOKEN_USER user_token
;
2000 TOKEN_PRIMARY_GROUP group_token
;
2003 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
2006 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
2007 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2009 buf
= xmalloc (blen
);
2010 result
= get_token_information (token
, TokenUser
,
2011 (LPVOID
)buf
, blen
, &needed
);
2014 memcpy (&user_token
, buf
, sizeof (user_token
));
2015 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
2017 domain
, &dlength
, &user_type
);
2025 strcpy (dflt_passwd
.pw_name
, uname
);
2026 /* Determine a reasonable uid value. */
2027 if (xstrcasecmp ("administrator", uname
) == 0)
2029 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2030 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2034 /* Use the last sub-authority value of the RID, the relative
2035 portion of the SID, as user/group ID. */
2036 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2038 /* Get group id and name. */
2039 result
= get_token_information (token
, TokenPrimaryGroup
,
2040 (LPVOID
)buf
, blen
, &needed
);
2041 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2043 buf
= xrealloc (buf
, blen
= needed
);
2044 result
= get_token_information (token
, TokenPrimaryGroup
,
2045 (LPVOID
)buf
, blen
, &needed
);
2049 memcpy (&group_token
, buf
, sizeof (group_token
));
2050 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2051 dlength
= sizeof (domain
);
2052 /* If we can get at the real Primary Group name, use that.
2053 Otherwise, the default group name was already set to
2054 "None" in globals_of_w32. */
2055 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2056 gname
, &glength
, NULL
, &dlength
,
2058 strcpy (dflt_group_name
, gname
);
2061 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2064 /* If security calls are not supported (presumably because we
2065 are running under Windows 9X), fallback to this: */
2066 else if (GetUserName (uname
, &ulength
))
2068 strcpy (dflt_passwd
.pw_name
, uname
);
2069 if (xstrcasecmp ("administrator", uname
) == 0)
2070 dflt_passwd
.pw_uid
= 0;
2072 dflt_passwd
.pw_uid
= 123;
2073 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2077 strcpy (dflt_passwd
.pw_name
, "unknown");
2078 dflt_passwd
.pw_uid
= 123;
2079 dflt_passwd
.pw_gid
= 123;
2081 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2083 /* Set dir and shell from environment variables. */
2084 if (w32_unicode_filenames
)
2086 wchar_t *home
= _wgetenv (L
"HOME");
2087 wchar_t *shell
= _wgetenv (L
"SHELL");
2089 /* Ensure HOME and SHELL are defined. */
2094 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2095 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2099 char *home
= getenv ("HOME");
2100 char *shell
= getenv ("SHELL");
2106 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2107 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2112 CloseHandle (token
);
2115 static HCRYPTPROV w32_crypto_hprov
;
2117 w32_init_crypt_random (void)
2119 if (!CryptAcquireContext (&w32_crypto_hprov
, NULL
, NULL
, PROV_RSA_FULL
,
2120 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
2122 DebPrint (("CryptAcquireContext failed with error %x\n",
2124 w32_crypto_hprov
= 0;
2131 w32_init_random (void *buf
, ptrdiff_t buflen
)
2133 if (!w32_crypto_hprov
)
2134 w32_init_crypt_random ();
2135 if (w32_crypto_hprov
)
2137 if (CryptGenRandom (w32_crypto_hprov
, buflen
, (BYTE
*)buf
))
2146 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2147 return ((rand () << 15) | rand ());
2156 /* Return the maximum length in bytes of a multibyte character
2157 sequence encoded in the current ANSI codepage. This is required to
2158 correctly walk the encoded file names one character at a time. */
2160 max_filename_mbslen (void)
2164 codepage_for_filenames (&cp_info
);
2165 return cp_info
.MaxCharSize
;
2168 /* Normalize filename by converting in-place all of its path
2169 separators to the separator specified by PATH_SEP. */
2172 normalize_filename (register char *fp
, char path_sep
)
2176 /* Always lower-case drive letters a-z, even if the filesystem
2177 preserves case in filenames.
2178 This is so filenames can be compared by string comparison
2179 functions that are case-sensitive. Even case-preserving filesystems
2180 do not distinguish case in drive letters. */
2183 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2191 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2197 /* Destructively turn backslashes into slashes. */
2199 dostounix_filename (register char *p
)
2201 normalize_filename (p
, '/');
2204 /* Destructively turn slashes into backslashes. */
2206 unixtodos_filename (register char *p
)
2208 normalize_filename (p
, '\\');
2211 /* Remove all CR's that are followed by a LF.
2212 (From msdos.c...probably should figure out a way to share it,
2213 although this code isn't going to ever change.) */
2215 crlf_to_lf (register int n
, register char *buf
)
2217 unsigned char *np
= (unsigned char *)buf
;
2218 unsigned char *startp
= np
;
2219 char *endp
= buf
+ n
;
2223 while (buf
< endp
- 1)
2227 if (*(++buf
) != 0x0a)
2238 /* Parse the root part of file name, if present. Return length and
2239 optionally store pointer to char after root. */
2241 parse_root (const char * name
, const char ** pPath
)
2243 const char * start
= name
;
2248 /* find the root name of the volume if given */
2249 if (isalpha (name
[0]) && name
[1] == ':')
2251 /* skip past drive specifier */
2253 if (IS_DIRECTORY_SEP (name
[0]))
2256 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2263 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2268 if (IS_DIRECTORY_SEP (name
[0]))
2275 return name
- start
;
2278 /* Get long base name for name; name is assumed to be absolute. */
2280 get_long_basename (char * name
, char * buf
, int size
)
2282 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2283 char fname_utf8
[MAX_UTF8_PATH
];
2287 /* Must be valid filename, no wild cards or other invalid characters. */
2288 if (strpbrk (name
, "*?|<>\""))
2291 if (w32_unicode_filenames
)
2293 wchar_t fname_utf16
[MAX_PATH
];
2294 WIN32_FIND_DATAW find_data_wide
;
2296 filename_to_utf16 (name
, fname_utf16
);
2297 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2298 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2299 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2303 char fname_ansi
[MAX_PATH
];
2304 WIN32_FIND_DATAA find_data_ansi
;
2306 filename_to_ansi (name
, fname_ansi
);
2307 /* If the ANSI name includes ? characters, it is not encodable
2308 in the ANSI codepage. In that case, we deliver the question
2309 marks to the caller; calling FindFirstFileA in this case
2310 could return some unrelated file name in the same
2312 if (_mbspbrk (fname_ansi
, "?"))
2314 /* Find the basename of fname_ansi. */
2315 char *p
= strrchr (fname_ansi
, '\\');
2321 cstatus
= filename_from_ansi (p
, fname_utf8
);
2325 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2326 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2327 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2331 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2332 memcpy (buf
, fname_utf8
, len
+ 1);
2336 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2337 FindClose (dir_handle
);
2342 /* Get long name for file, if possible (assumed to be absolute). */
2344 w32_get_long_filename (const char * name
, char * buf
, int size
)
2349 char full
[ MAX_UTF8_PATH
];
2352 len
= strlen (name
);
2353 if (len
>= MAX_UTF8_PATH
)
2356 /* Use local copy for destructive modification. */
2357 memcpy (full
, name
, len
+1);
2358 unixtodos_filename (full
);
2360 /* Copy root part verbatim. */
2361 len
= parse_root (full
, (const char **)&p
);
2362 memcpy (o
, full
, len
);
2367 while (p
!= NULL
&& *p
)
2370 p
= strchr (q
, '\\');
2372 len
= get_long_basename (full
, o
, size
);
2395 w32_get_short_filename (const char * name
, char * buf
, int size
)
2397 if (w32_unicode_filenames
)
2399 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2400 unsigned int retval
;
2402 filename_to_utf16 (name
, name_utf16
);
2403 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2404 if (retval
&& retval
< size
)
2405 filename_from_utf16 (short_name
, buf
);
2410 char name_ansi
[MAX_PATH
];
2412 filename_to_ansi (name
, name_ansi
);
2413 return GetShortPathNameA (name_ansi
, buf
, size
);
2417 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2418 MS-Windows ANSI codepage. If FILENAME includes characters not
2419 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2420 if it exists. This is needed because the w32 build wants to
2421 support file names outside of the system locale, but image
2422 libraries typically don't support wide (a.k.a. "Unicode") APIs
2423 required for that. */
2426 ansi_encode_filename (Lisp_Object filename
)
2428 Lisp_Object encoded_filename
;
2429 char fname
[MAX_PATH
];
2431 filename_to_ansi (SSDATA (filename
), fname
);
2432 if (_mbspbrk (fname
, "?"))
2434 char shortname
[MAX_PATH
];
2436 if (w32_get_short_filename (SSDATA (filename
), shortname
, MAX_PATH
))
2438 dostounix_filename (shortname
);
2439 encoded_filename
= build_string (shortname
);
2442 encoded_filename
= build_unibyte_string (fname
);
2445 encoded_filename
= build_unibyte_string (fname
);
2446 return encoded_filename
;
2450 is_unc_volume (const char *filename
)
2452 const char *ptr
= filename
;
2454 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2457 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2463 /* Emulate the Posix unsetenv. */
2465 unsetenv (const char *name
)
2470 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2475 name_len
= strlen (name
);
2476 /* MS docs says an environment variable cannot be longer than 32K. */
2477 if (name_len
> 32767)
2482 /* It is safe to use 'alloca' with 32K size, since the stack is at
2483 least 2MB, and we set it to 8MB in the link command line. */
2484 var
= alloca (name_len
+ 2);
2485 strncpy (var
, name
, name_len
);
2486 var
[name_len
++] = '=';
2487 var
[name_len
] = '\0';
2488 return _putenv (var
);
2491 /* MS _putenv doesn't support removing a variable when the argument
2492 does not include the '=' character, so we fix that here. */
2494 sys_putenv (char *str
)
2496 const char *const name_end
= strchr (str
, '=');
2498 if (name_end
== NULL
)
2500 /* Remove the variable from the environment. */
2501 return unsetenv (str
);
2504 if (strncmp (str
, "TZ=<", 4) == 0)
2506 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2507 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2508 and to the undocumented placeholder "ZZZ" otherwise. */
2509 bool supported_abbr
= true;
2510 for (char *p
= str
+ 4; *p
; p
++)
2512 if (('0' <= *p
&& *p
<= '9') || *p
== '-' || *p
== '+')
2513 supported_abbr
= false;
2519 abbrlen
= p
- (str
+ 4);
2520 memmove (str
+ 3, str
+ 4, abbrlen
);
2525 memset (str
+ 3, 'Z', abbrlen
);
2527 memmove (str
+ 3 + abbrlen
, p
+ 1, strlen (p
));
2533 return _putenv (str
);
2536 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2539 w32_get_resource (const char *key
, LPDWORD lpdwtype
)
2542 HKEY hrootkey
= NULL
;
2545 /* Check both the current user and the local machine to see if
2546 we have any resources. */
2548 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2552 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2553 && (lpvalue
= xmalloc (cbData
)) != NULL
2554 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2556 RegCloseKey (hrootkey
);
2562 RegCloseKey (hrootkey
);
2565 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2569 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2570 && (lpvalue
= xmalloc (cbData
)) != NULL
2571 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2573 RegCloseKey (hrootkey
);
2579 RegCloseKey (hrootkey
);
2585 /* The argv[] array holds ANSI-encoded strings, and so this function
2586 works with ANS_encoded strings. */
2588 init_environment (char ** argv
)
2590 static const char * const tempdirs
[] = {
2591 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2596 const int imax
= ARRAYELTS (tempdirs
);
2598 /* Implementation note: This function explicitly works with ANSI
2599 file names, not with UTF-8 encoded file names. This is because
2600 this function pushes variables into the Emacs's environment, and
2601 the environment variables are always assumed to be in the
2602 locale-specific encoding. Do NOT call any functions that accept
2603 UTF-8 file names from this function! */
2605 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2606 temporary files and assume "/tmp" if $TMPDIR is unset, which
2607 will break on DOS/Windows. Refuse to work if we cannot find
2608 a directory, not even "c:/", usable for that purpose. */
2609 for (i
= 0; i
< imax
; i
++)
2611 const char *tmp
= tempdirs
[i
];
2614 tmp
= getenv (tmp
+ 1);
2615 /* Note that `access' can lie to us if the directory resides on a
2616 read-only filesystem, like CD-ROM or a write-protected floppy.
2617 The only way to be really sure is to actually create a file and
2618 see if it succeeds. But I think that's too much to ask. */
2620 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2621 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2623 char * var
= alloca (strlen (tmp
) + 8);
2624 sprintf (var
, "TMPDIR=%s", tmp
);
2625 _putenv (strdup (var
));
2632 Fcons (build_string ("no usable temporary directories found!!"),
2634 "While setting TMPDIR: ");
2636 /* Check for environment variables and use registry settings if they
2637 don't exist. Fallback on default values where applicable. */
2642 char locale_name
[32];
2643 char default_home
[MAX_PATH
];
2646 static const struct env_entry
2649 const char * def_value
;
2652 /* If the default value is NULL, we will use the value from the
2653 outside environment or the Registry, but will not push the
2654 variable into the Emacs environment if it is defined neither
2655 in the Registry nor in the outside environment. */
2657 {"PRELOAD_WINSOCK", NULL
},
2658 {"emacs_dir", "C:/emacs"},
2659 {"EMACSLOADPATH", NULL
},
2660 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2661 {"EMACSDATA", NULL
},
2662 {"EMACSPATH", NULL
},
2669 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2671 /* We need to copy dflt_envvars[] and work on the copy because we
2672 don't want the dumped Emacs to inherit the values of
2673 environment variables we saw during dumping (which could be on
2674 a different system). The defaults above must be left intact. */
2675 struct env_entry env_vars
[N_ENV_VARS
];
2677 for (i
= 0; i
< N_ENV_VARS
; i
++)
2678 env_vars
[i
] = dflt_envvars
[i
];
2680 /* For backwards compatibility, check if a .emacs file exists in C:/
2681 If not, then we can try to default to the appdata directory under the
2682 user's profile, which is more likely to be writable. */
2683 if (sys_access ("C:/.emacs", F_OK
) != 0)
2685 HRESULT profile_result
;
2686 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2687 of Windows 95 and NT4 that have not been updated to include
2689 ShGetFolderPath_fn get_folder_path
;
2690 get_folder_path
= (ShGetFolderPath_fn
)
2691 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2693 if (get_folder_path
!= NULL
)
2695 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2698 /* If we can't get the appdata dir, revert to old behavior. */
2699 if (profile_result
== S_OK
)
2701 env_vars
[0].def_value
= default_home
;
2707 /* Get default locale info and use it for LANG. */
2708 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2709 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2710 locale_name
, sizeof (locale_name
)))
2712 for (i
= 0; i
< N_ENV_VARS
; i
++)
2714 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2716 env_vars
[i
].def_value
= locale_name
;
2722 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2724 /* Treat emacs_dir specially: set it unconditionally based on our
2728 char modname
[MAX_PATH
];
2730 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2732 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2736 if ((p
= _mbsrchr (modname
, '\\'))
2737 /* From bin means installed Emacs, from src means uninstalled. */
2738 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2740 char buf
[SET_ENV_BUF_SIZE
];
2741 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2744 for (p
= modname
; *p
; p
= CharNext (p
))
2745 if (*p
== '\\') *p
= '/';
2747 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2748 _putenv (strdup (buf
));
2749 /* If we are running from the Posix-like build tree, define
2750 SHELL to point to our own cmdproxy. The loop below will
2751 then disregard PATH_EXEC and the default value. */
2752 if (within_build_tree
)
2754 _snprintf (buf
, sizeof (buf
) - 1,
2755 "SHELL=%s/nt/cmdproxy.exe", modname
);
2756 _putenv (strdup (buf
));
2761 for (i
= 0; i
< N_ENV_VARS
; i
++)
2763 if (!getenv (env_vars
[i
].name
))
2766 char bufc
[SET_ENV_BUF_SIZE
];
2768 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2769 /* Also ignore empty environment variables. */
2774 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2776 /* Look for cmdproxy.exe in every directory in
2777 PATH_EXEC. FIXME: This does not find cmdproxy
2778 in nt/ when we run uninstalled. */
2779 char fname
[MAX_PATH
];
2780 const char *pstart
= PATH_EXEC
, *pend
;
2783 pend
= _mbschr (pstart
, ';');
2785 pend
= pstart
+ strlen (pstart
);
2786 /* Be defensive against series of ;;; characters. */
2789 strncpy (fname
, pstart
, pend
- pstart
);
2790 fname
[pend
- pstart
] = '/';
2791 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2792 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2794 if (sys_access (bufc
, F_OK
) == 0)
2807 /* If not found in any directory, use the
2808 default as the last resort. */
2809 lpval
= (char *)env_vars
[i
].def_value
;
2810 dwType
= REG_EXPAND_SZ
;
2816 lpval
= (char *)env_vars
[i
].def_value
;
2817 dwType
= REG_EXPAND_SZ
;
2819 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2820 Vdelayed_warnings_list
2822 (listn (CONSTYPE_HEAP
, 2,
2823 intern ("initialization"), build_string
2824 ("Use of `C:\\.emacs' without defining `HOME'\n"
2825 "in the environment is deprecated, "
2826 "see `Windows HOME' in the Emacs manual.")),
2827 Vdelayed_warnings_list
);
2832 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2834 if (dwType
== REG_EXPAND_SZ
)
2835 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2836 else if (dwType
== REG_SZ
)
2837 strcpy (buf1
, (char *)lpval
);
2838 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2840 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2842 _putenv (strdup (buf2
));
2852 /* Rebuild system configuration to reflect invoking system. */
2853 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2855 /* Another special case: on NT, the PATH variable is actually named
2856 "Path" although cmd.exe (perhaps NT itself) arranges for
2857 environment variable lookup and setting to be case insensitive.
2858 However, Emacs assumes a fully case sensitive environment, so we
2859 need to change "Path" to "PATH" to match the expectations of
2860 various elisp packages. We do this by the sneaky method of
2861 modifying the string in the C runtime environ entry.
2863 The same applies to COMSPEC. */
2866 const char *path
= "PATH=";
2867 int path_len
= strlen (path
);
2868 const char *comspec
= "COMSPEC=";
2869 int comspec_len
= strlen (comspec
);
2871 for (envp
= environ
; *envp
; envp
++)
2872 if (_strnicmp (*envp
, path
, path_len
) == 0)
2873 memcpy (*envp
, path
, path_len
);
2874 else if (_strnicmp (*envp
, comspec
, comspec_len
) == 0)
2875 memcpy (*envp
, comspec
, comspec_len
);
2877 /* Make the same modification to `process-environment' which has
2878 already been initialized in set_initial_environment. */
2879 for (Lisp_Object env
= Vprocess_environment
; CONSP (env
); env
= XCDR (env
))
2881 Lisp_Object entry
= XCAR (env
);
2882 if (_strnicmp (SDATA (entry
), path
, path_len
) == 0)
2883 for (int i
= 0; i
< path_len
; i
++)
2884 SSET (entry
, i
, path
[i
]);
2885 else if (_strnicmp (SDATA (entry
), comspec
, comspec_len
) == 0)
2886 for (int i
= 0; i
< comspec_len
; i
++)
2887 SSET (entry
, i
, comspec
[i
]);
2891 /* Remember the initial working directory for getcwd. */
2892 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2893 Does it matter anywhere in Emacs? */
2894 if (w32_unicode_filenames
)
2896 wchar_t wstartup_dir
[MAX_PATH
];
2898 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2900 filename_from_utf16 (wstartup_dir
, startup_dir
);
2904 char astartup_dir
[MAX_PATH
];
2906 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2908 filename_from_ansi (astartup_dir
, startup_dir
);
2912 static char modname
[MAX_PATH
];
2914 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2919 /* Determine if there is a middle mouse button, to allow parse_button
2920 to decide whether right mouse events should be mouse-2 or
2922 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2927 /* Called from expand-file-name when default-directory is not a string. */
2930 emacs_root_dir (void)
2932 static char root_dir
[MAX_UTF8_PATH
];
2935 p
= getenv ("emacs_dir");
2938 filename_from_ansi (p
, root_dir
);
2939 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2940 dostounix_filename (root_dir
);
2944 #include <sys/timeb.h>
2946 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2948 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2953 tv
->tv_sec
= tb
.time
;
2954 tv
->tv_usec
= tb
.millitm
* 1000L;
2955 /* Implementation note: _ftime sometimes doesn't update the dstflag
2956 according to the new timezone when the system timezone is
2957 changed. We could fix that by using GetSystemTime and
2958 GetTimeZoneInformation, but that doesn't seem necessary, since
2959 Emacs always calls gettimeofday with the 2nd argument NULL (see
2960 current_emacs_time). */
2963 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2964 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2969 /* Emulate fdutimens. */
2971 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2972 TIMESPEC[0] and TIMESPEC[1], respectively.
2973 FD must be either negative -- in which case it is ignored --
2974 or a file descriptor that is open on FILE.
2975 If FD is nonnegative, then FILE can be NULL, which means
2976 use just futimes instead of utimes.
2977 If TIMESPEC is null, FAIL.
2978 Return 0 on success, -1 (setting errno) on failure. */
2981 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2988 if (fd
< 0 && !file
)
2993 /* _futime's prototype defines 2nd arg as having the type 'struct
2994 _utimbuf', while utime needs to accept 'struct utimbuf' for
2995 compatibility with Posix. So we need to use 2 different (but
2996 equivalent) types to avoid compiler warnings, sigh. */
2999 struct _utimbuf _ut
;
3001 _ut
.actime
= timespec
[0].tv_sec
;
3002 _ut
.modtime
= timespec
[1].tv_sec
;
3003 return _futime (fd
, &_ut
);
3009 ut
.actime
= timespec
[0].tv_sec
;
3010 ut
.modtime
= timespec
[1].tv_sec
;
3011 /* Call 'utime', which is implemented below, not the MS library
3012 function, which fails on directories. */
3013 return utime (file
, &ut
);
3018 /* ------------------------------------------------------------------------- */
3019 /* IO support and wrapper functions for the Windows API. */
3020 /* ------------------------------------------------------------------------- */
3022 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3023 on network directories, so we handle that case here.
3024 (Ulrich Leodolter, 1/11/95). */
3026 sys_ctime (const time_t *t
)
3028 char *str
= (char *) ctime (t
);
3029 return (str
? str
: (char *)"Sun Jan 01 00:00:00 1970");
3032 /* Emulate sleep...we could have done this with a define, but that
3033 would necessitate including windows.h in the files that used it.
3034 This is much easier. */
3036 sys_sleep (int seconds
)
3038 Sleep (seconds
* 1000);
3041 /* Internal MSVC functions for low-level descriptor munging */
3042 extern int __cdecl
_set_osfhnd (int fd
, long h
);
3043 extern int __cdecl
_free_osfhnd (int fd
);
3045 /* parallel array of private info on file handles */
3046 filedesc fd_info
[ MAXDESC
];
3048 typedef struct volume_info_data
{
3049 struct volume_info_data
* next
;
3051 /* time when info was obtained */
3054 /* actual volume info */
3063 /* Global referenced by various functions. */
3064 static volume_info_data volume_info
;
3066 /* Vector to indicate which drives are local and fixed (for which cached
3067 data never expires). */
3068 static BOOL fixed_drives
[26];
3070 /* Consider cached volume information to be stale if older than 10s,
3071 at least for non-local drives. Info for fixed drives is never stale. */
3072 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3073 #define VOLINFO_STILL_VALID( root_dir, info ) \
3074 ( ( isalpha (root_dir[0]) && \
3075 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3076 || GetTickCount () - info->timestamp < 10000 )
3078 /* Cache support functions. */
3080 /* Simple linked list with linear search is sufficient. */
3081 static volume_info_data
*volume_cache
= NULL
;
3083 static volume_info_data
*
3084 lookup_volume_info (char * root_dir
)
3086 volume_info_data
* info
;
3088 for (info
= volume_cache
; info
; info
= info
->next
)
3089 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
3095 add_volume_info (char * root_dir
, volume_info_data
* info
)
3097 info
->root_dir
= xstrdup (root_dir
);
3098 unixtodos_filename (info
->root_dir
);
3099 info
->next
= volume_cache
;
3100 volume_cache
= info
;
3104 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3105 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3106 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3107 static volume_info_data
*
3108 GetCachedVolumeInformation (char * root_dir
)
3110 volume_info_data
* info
;
3111 char default_root
[ MAX_UTF8_PATH
];
3112 char name
[MAX_PATH
+1];
3113 char type
[MAX_PATH
+1];
3115 /* NULL for root_dir means use root from current directory. */
3116 if (root_dir
== NULL
)
3118 if (w32_unicode_filenames
)
3120 wchar_t curdirw
[MAX_PATH
];
3122 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3124 filename_from_utf16 (curdirw
, default_root
);
3128 char curdira
[MAX_PATH
];
3130 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3132 filename_from_ansi (curdira
, default_root
);
3134 parse_root (default_root
, (const char **)&root_dir
);
3136 root_dir
= default_root
;
3139 /* Local fixed drives can be cached permanently. Removable drives
3140 cannot be cached permanently, since the volume name and serial
3141 number (if nothing else) can change. Remote drives should be
3142 treated as if they are removable, since there is no sure way to
3143 tell whether they are or not. Also, the UNC association of drive
3144 letters mapped to remote volumes can be changed at any time (even
3145 by other processes) without notice.
3147 As a compromise, so we can benefit from caching info for remote
3148 volumes, we use a simple expiry mechanism to invalidate cache
3149 entries that are more than ten seconds old. */
3152 /* No point doing this, because WNetGetConnection is even slower than
3153 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3154 GetDriveType is about the only call of this type which does not
3155 involve network access, and so is extremely quick). */
3157 /* Map drive letter to UNC if remote. */
3158 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3160 char remote_name
[ 256 ];
3161 char drive
[3] = { root_dir
[0], ':' };
3163 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3165 /* do something */ ;
3169 info
= lookup_volume_info (root_dir
);
3171 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3177 /* Info is not cached, or is stale. */
3178 if (w32_unicode_filenames
)
3180 wchar_t root_w
[MAX_PATH
];
3181 wchar_t name_w
[MAX_PATH
+1];
3182 wchar_t type_w
[MAX_PATH
+1];
3184 filename_to_utf16 (root_dir
, root_w
);
3185 if (!GetVolumeInformationW (root_w
,
3186 name_w
, sizeof (name_w
),
3190 type_w
, sizeof (type_w
)))
3192 /* Hmm... not really 100% correct, as these 2 are not file
3194 filename_from_utf16 (name_w
, name
);
3195 filename_from_utf16 (type_w
, type
);
3199 char root_a
[MAX_PATH
];
3200 char name_a
[MAX_PATH
+1];
3201 char type_a
[MAX_PATH
+1];
3203 filename_to_ansi (root_dir
, root_a
);
3204 if (!GetVolumeInformationA (root_a
,
3205 name_a
, sizeof (name_a
),
3209 type_a
, sizeof (type_a
)))
3211 filename_from_ansi (name_a
, name
);
3212 filename_from_ansi (type_a
, type
);
3215 /* Cache the volume information for future use, overwriting existing
3216 entry if present. */
3219 info
= xmalloc (sizeof (volume_info_data
));
3220 add_volume_info (root_dir
, info
);
3228 info
->name
= xstrdup (name
);
3229 unixtodos_filename (info
->name
);
3230 info
->serialnum
= serialnum
;
3231 info
->maxcomp
= maxcomp
;
3232 info
->flags
= flags
;
3233 info
->type
= xstrdup (type
);
3234 info
->timestamp
= GetTickCount ();
3240 /* Get information on the volume where NAME is held; set path pointer to
3241 start of pathname in NAME (past UNC header\volume header if present),
3242 if pPath is non-NULL.
3244 Note: if NAME includes symlinks, the information is for the volume
3245 of the symlink, not of its target. That's because, even though
3246 GetVolumeInformation returns information about the symlink target
3247 of its argument, we only pass the root directory to
3248 GetVolumeInformation, not the full NAME. */
3250 get_volume_info (const char * name
, const char ** pPath
)
3252 char temp
[MAX_UTF8_PATH
];
3253 char *rootname
= NULL
; /* default to current volume */
3254 volume_info_data
* info
;
3255 int root_len
= parse_root (name
, pPath
);
3260 /* Copy the root name of the volume, if given. */
3263 strncpy (temp
, name
, root_len
);
3264 temp
[root_len
] = '\0';
3265 unixtodos_filename (temp
);
3269 info
= GetCachedVolumeInformation (rootname
);
3272 /* Set global referenced by other functions. */
3273 volume_info
= *info
;
3279 /* Determine if volume is FAT format (ie. only supports short 8.3
3280 names); also set path pointer to start of pathname in name, if
3281 pPath is non-NULL. */
3283 is_fat_volume (const char * name
, const char ** pPath
)
3285 if (get_volume_info (name
, pPath
))
3286 return (volume_info
.maxcomp
== 12);
3290 /* Convert all slashes in a filename to backslashes, and map filename
3291 to a valid 8.3 name if necessary. The result is a pointer to a
3292 static buffer, so CAVEAT EMPTOR! */
3293 const char *map_w32_filename (const char *, const char **);
3296 map_w32_filename (const char * name
, const char ** pPath
)
3298 static char shortname
[MAX_UTF8_PATH
];
3299 char * str
= shortname
;
3302 const char * save_name
= name
;
3304 if (strlen (name
) >= sizeof (shortname
))
3306 /* Return a filename which will cause callers to fail. */
3307 strcpy (shortname
, "?");
3311 if (!fatal_error_in_progress
/* disable fancy processing during crash */
3312 && is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3314 register int left
= 8; /* maximum number of chars in part */
3315 register int extn
= 0; /* extension added? */
3316 register int dots
= 2; /* maximum number of dots allowed */
3319 *str
++ = *name
++; /* skip past UNC header */
3321 while ((c
= *name
++))
3328 *str
++ = (c
== ':' ? ':' : '\\');
3329 extn
= 0; /* reset extension flags */
3330 dots
= 2; /* max 2 dots */
3331 left
= 8; /* max length 8 for main part */
3336 /* Convert path components of the form .xxx to _xxx,
3337 but leave . and .. as they are. This allows .emacs
3338 to be read as _emacs, for example. */
3342 IS_DIRECTORY_SEP (*name
))
3357 extn
= 1; /* we've got an extension */
3358 left
= 3; /* 3 chars in extension */
3362 /* any embedded dots after the first are converted to _ */
3367 case '#': /* don't lose these, they're important */
3369 str
[-1] = c
; /* replace last character of part */
3372 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3374 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3376 dots
= 0; /* started a path component */
3385 strcpy (shortname
, name
);
3386 unixtodos_filename (shortname
);
3390 *pPath
= shortname
+ (path
- save_name
);
3396 is_exec (const char * name
)
3398 char * p
= strrchr (name
, '.');
3401 && (xstrcasecmp (p
, ".exe") == 0 ||
3402 xstrcasecmp (p
, ".com") == 0 ||
3403 xstrcasecmp (p
, ".bat") == 0 ||
3404 xstrcasecmp (p
, ".cmd") == 0));
3407 /* Emulate the Unix directory procedures opendir, closedir, and
3408 readdir. We rename them to sys_* names because some versions of
3409 MinGW startup code call opendir and readdir to glob wildcards, and
3410 the code that calls them doesn't grok UTF-8 encoded file names we
3411 produce in dirent->d_name[]. */
3413 struct dirent dir_static
; /* simulated directory contents */
3414 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3415 static int dir_is_fat
;
3416 static char dir_pathname
[MAX_UTF8_PATH
];
3417 static WIN32_FIND_DATAW dir_find_data_w
;
3418 static WIN32_FIND_DATAA dir_find_data_a
;
3419 #define DIR_FIND_DATA_W 1
3420 #define DIR_FIND_DATA_A 2
3421 static int last_dir_find_data
= -1;
3423 /* Support shares on a network resource as subdirectories of a read-only
3425 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3426 static HANDLE
open_unc_volume (const char *);
3427 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3428 static void close_unc_volume (HANDLE
);
3431 sys_opendir (const char *filename
)
3435 /* Opening is done by FindFirstFile. However, a read is inherent to
3436 this operation, so we defer the open until read time. */
3438 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3440 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3443 /* Note: We don't support traversal of UNC volumes via symlinks.
3444 Doing so would mean punishing 99.99% of use cases by resolving
3445 all the possible symlinks in FILENAME, recursively. */
3446 if (is_unc_volume (filename
))
3448 wnet_enum_handle
= open_unc_volume (filename
);
3449 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3453 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3460 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3461 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3462 /* Note: We don't support symlinks to file names on FAT volumes.
3463 Doing so would mean punishing 99.99% of use cases by resolving
3464 all the possible symlinks in FILENAME, recursively. */
3465 dir_is_fat
= is_fat_volume (filename
, NULL
);
3471 sys_closedir (DIR *dirp
)
3473 /* If we have a find-handle open, close it. */
3474 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3476 FindClose (dir_find_handle
);
3477 dir_find_handle
= INVALID_HANDLE_VALUE
;
3479 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3481 close_unc_volume (wnet_enum_handle
);
3482 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3484 xfree ((char *) dirp
);
3488 sys_readdir (DIR *dirp
)
3490 int downcase
= !NILP (Vw32_downcase_file_names
);
3492 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3494 if (!read_unc_volume (wnet_enum_handle
,
3495 dir_find_data_w
.cFileName
,
3496 dir_find_data_a
.cFileName
,
3500 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3501 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3503 char filename
[MAX_UTF8_PATH
];
3505 bool last_slash
= true;
3507 /* Note: We don't need to worry about dir_pathname being longer
3508 than MAX_UTF8_PATH, as sys_opendir already took care of that
3509 when it called map_w32_filename: that function will put a "?"
3510 in its return value in that case, thus failing all the calls
3512 strcpy (filename
, dir_pathname
);
3513 ln
= strlen (filename
);
3514 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3517 /* Note: No need to resolve symlinks in FILENAME, because
3518 FindFirst opens the directory that is the target of a
3520 if (w32_unicode_filenames
)
3522 wchar_t fnw
[MAX_PATH
+ 2];
3524 filename_to_utf16 (filename
, fnw
);
3526 wcscat (fnw
, L
"\\");
3528 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3532 char fna
[MAX_PATH
+ 2];
3534 filename_to_ansi (filename
, fna
);
3538 /* If FILENAME is not representable by the current ANSI
3539 codepage, we don't want FindFirstFileA to interpret the
3540 '?' characters as a wildcard. */
3541 if (_mbspbrk (fna
, "?"))
3542 dir_find_handle
= INVALID_HANDLE_VALUE
;
3544 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3547 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3549 /* Any changes in the value of errno here should be in sync
3550 with what directory_files_internal does when it calls
3552 switch (GetLastError ())
3554 /* Windows uses this value when FindFirstFile finds no
3555 files that match the wildcard. This is not supposed
3556 to happen, since our wildcard is "*", but just in
3557 case, if there's some weird empty directory with not
3558 even "." and ".." entries... */
3559 case ERROR_FILE_NOT_FOUND
:
3564 case ERROR_ACCESS_DENIED
:
3565 case ERROR_NETWORK_ACCESS_DENIED
:
3568 case ERROR_PATH_NOT_FOUND
:
3569 case ERROR_INVALID_DRIVE
:
3570 case ERROR_NOT_READY
:
3571 case ERROR_BAD_NETPATH
:
3572 case ERROR_BAD_NET_NAME
:
3579 else if (w32_unicode_filenames
)
3581 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3589 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3596 /* Emacs never uses this value, so don't bother making it match
3597 value returned by stat(). */
3598 dir_static
.d_ino
= 1;
3600 if (w32_unicode_filenames
)
3602 if (downcase
|| dir_is_fat
)
3604 wchar_t tem
[MAX_PATH
];
3606 wcscpy (tem
, dir_find_data_w
.cFileName
);
3608 filename_from_utf16 (tem
, dir_static
.d_name
);
3611 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3612 last_dir_find_data
= DIR_FIND_DATA_W
;
3618 /* If the file name in cFileName[] includes `?' characters, it
3619 means the original file name used characters that cannot be
3620 represented by the current ANSI codepage. To avoid total
3621 lossage, retrieve the short 8+3 alias of the long file
3623 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3625 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3626 /* 8+3 aliases are returned in all caps, which could break
3627 various alists that look at filenames' extensions. */
3630 else if (downcase
|| dir_is_fat
)
3631 strcpy (tem
, dir_find_data_a
.cFileName
);
3633 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3634 if (downcase
|| dir_is_fat
)
3637 filename_from_ansi (tem
, dir_static
.d_name
);
3639 last_dir_find_data
= DIR_FIND_DATA_A
;
3642 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3643 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3644 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3650 open_unc_volume (const char *path
)
3652 const char *fn
= map_w32_filename (path
, NULL
);
3656 if (w32_unicode_filenames
)
3659 wchar_t fnw
[MAX_PATH
];
3661 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3662 nrw
.dwType
= RESOURCETYPE_DISK
;
3663 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3664 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3665 nrw
.lpLocalName
= NULL
;
3666 filename_to_utf16 (fn
, fnw
);
3667 nrw
.lpRemoteName
= fnw
;
3668 nrw
.lpComment
= NULL
;
3669 nrw
.lpProvider
= NULL
;
3671 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3672 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3679 nra
.dwScope
= RESOURCE_GLOBALNET
;
3680 nra
.dwType
= RESOURCETYPE_DISK
;
3681 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3682 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3683 nra
.lpLocalName
= NULL
;
3684 filename_to_ansi (fn
, fna
);
3685 nra
.lpRemoteName
= fna
;
3686 nra
.lpComment
= NULL
;
3687 nra
.lpProvider
= NULL
;
3689 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3690 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3692 if (result
== NO_ERROR
)
3696 /* Make sure directory_files_internal reports a sensible error. */
3698 return INVALID_HANDLE_VALUE
;
3703 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3708 DWORD bufsize
= 512;
3712 if (w32_unicode_filenames
)
3717 buffer
= alloca (bufsize
);
3718 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3719 if (result
!= NO_ERROR
)
3721 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3722 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3724 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3726 wcsncpy (fname_w
, ptrw
, size
);
3731 int dbcs_p
= max_filename_mbslen () > 1;
3734 buffer
= alloca (bufsize
);
3735 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3736 if (result
!= NO_ERROR
)
3738 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3741 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3744 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3745 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3748 strncpy (fname_a
, ptra
, size
);
3756 close_unc_volume (HANDLE henum
)
3758 if (henum
!= INVALID_HANDLE_VALUE
)
3759 WNetCloseEnum (henum
);
3763 unc_volume_file_attributes (const char *path
)
3768 henum
= open_unc_volume (path
);
3769 if (henum
== INVALID_HANDLE_VALUE
)
3772 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3774 close_unc_volume (henum
);
3779 /* Ensure a network connection is authenticated. */
3781 logon_network_drive (const char *path
)
3783 char share
[MAX_UTF8_PATH
];
3790 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3791 drvtype
= DRIVE_REMOTE
;
3792 else if (path
[0] == '\0' || path
[1] != ':')
3793 drvtype
= GetDriveType (NULL
);
3800 drvtype
= GetDriveType (drive
);
3803 /* Only logon to networked drives. */
3804 if (drvtype
!= DRIVE_REMOTE
)
3808 strncpy (share
, path
, MAX_UTF8_PATH
);
3809 /* Truncate to just server and share name. */
3810 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3812 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3819 if (w32_unicode_filenames
)
3821 NETRESOURCEW resourcew
;
3822 wchar_t share_w
[MAX_PATH
];
3824 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3825 resourcew
.dwType
= RESOURCETYPE_DISK
;
3826 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3827 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3828 resourcew
.lpLocalName
= NULL
;
3829 filename_to_utf16 (share
, share_w
);
3830 resourcew
.lpRemoteName
= share_w
;
3831 resourcew
.lpProvider
= NULL
;
3833 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3837 NETRESOURCEA resourcea
;
3838 char share_a
[MAX_PATH
];
3840 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3841 resourcea
.dwType
= RESOURCETYPE_DISK
;
3842 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3843 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3844 resourcea
.lpLocalName
= NULL
;
3845 filename_to_ansi (share
, share_a
);
3846 resourcea
.lpRemoteName
= share_a
;
3847 resourcea
.lpProvider
= NULL
;
3849 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3855 case ERROR_ALREADY_ASSIGNED
:
3857 case ERROR_ACCESS_DENIED
:
3858 case ERROR_LOGON_FAILURE
:
3864 case ERROR_BAD_NET_NAME
:
3865 case ERROR_NO_NET_OR_BAD_PATH
:
3866 case ERROR_NO_NETWORK
:
3867 case ERROR_CANCELLED
:
3874 /* Emulate faccessat(2). */
3876 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3880 if (dirfd
!= AT_FDCWD
3881 && !(IS_DIRECTORY_SEP (path
[0])
3882 || IS_DEVICE_SEP (path
[1])))
3888 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3889 newer versions blow up when passed D_OK. */
3890 path
= map_w32_filename (path
, NULL
);
3891 /* If the last element of PATH is a symlink, we need to resolve it
3892 to get the attributes of its target file. Note: any symlinks in
3893 PATH elements other than the last one are transparently resolved
3894 by GetFileAttributes below. */
3895 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3896 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3897 path
= chase_symlinks (path
);
3899 if (w32_unicode_filenames
)
3901 wchar_t path_w
[MAX_PATH
];
3903 filename_to_utf16 (path
, path_w
);
3904 attributes
= GetFileAttributesW (path_w
);
3908 char path_a
[MAX_PATH
];
3910 filename_to_ansi (path
, path_a
);
3911 attributes
= GetFileAttributesA (path_a
);
3914 if (attributes
== -1)
3916 DWORD w32err
= GetLastError ();
3920 case ERROR_INVALID_NAME
:
3921 case ERROR_BAD_PATHNAME
:
3922 if (is_unc_volume (path
))
3924 attributes
= unc_volume_file_attributes (path
);
3925 if (attributes
== -1)
3933 case ERROR_FILE_NOT_FOUND
:
3934 case ERROR_BAD_NETPATH
:
3945 if ((mode
& X_OK
) != 0
3946 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3951 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3956 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3964 /* A special test for DIRNAME being a directory accessible by the
3965 current user. This is needed because the security permissions in
3966 directory's ACLs are not visible in the Posix-style mode bits
3967 returned by 'stat' and in attributes returned by GetFileAttributes.
3968 So a directory would seem like it's readable by the current user,
3969 but will in fact error out with EACCES when they actually try. */
3971 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
3973 char pattern
[MAX_UTF8_PATH
];
3974 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
3977 /* Network volumes need a different reading method. */
3978 if (is_unc_volume (dirname
))
3980 void *read_result
= NULL
;
3981 wchar_t fnw
[MAX_PATH
];
3984 dh
= open_unc_volume (dirname
);
3985 if (dh
!= INVALID_HANDLE_VALUE
)
3987 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
3988 close_unc_volume (dh
);
3990 /* Treat empty volumes as accessible. */
3991 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
3994 /* Note: map_w32_filename makes sure DIRNAME is not longer than
3996 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
3998 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
3999 opens the directory that is the target of a symlink. */
4000 if (w32_unicode_filenames
)
4002 wchar_t pat_w
[MAX_PATH
+ 2];
4003 WIN32_FIND_DATAW dfd_w
;
4005 filename_to_utf16 (pattern
, pat_w
);
4007 wcscat (pat_w
, L
"\\");
4008 wcscat (pat_w
, L
"*");
4009 dh
= FindFirstFileW (pat_w
, &dfd_w
);
4013 char pat_a
[MAX_PATH
+ 2];
4014 WIN32_FIND_DATAA dfd_a
;
4016 filename_to_ansi (pattern
, pat_a
);
4018 strcpy (pat_a
, "\\");
4019 strcat (pat_a
, "*");
4020 /* In case DIRNAME cannot be expressed in characters from the
4021 current ANSI codepage. */
4022 if (_mbspbrk (pat_a
, "?"))
4023 dh
= INVALID_HANDLE_VALUE
;
4025 dh
= FindFirstFileA (pat_a
, &dfd_a
);
4028 if (dh
== INVALID_HANDLE_VALUE
)
4034 /* A version of 'access' to be used locally with file names in
4035 locale-specific encoding. Does not resolve symlinks and does not
4036 support file names on FAT12 and FAT16 volumes, but that's OK, since
4037 we only invoke this function for files inside the Emacs source or
4038 installation tree, on directories (so any symlinks should have the
4039 directory bit set), and on short file names such as "C:/.emacs". */
4041 sys_access (const char *fname
, int mode
)
4043 char fname_copy
[MAX_PATH
], *p
;
4046 strcpy (fname_copy
, fname
);
4047 /* Do the equivalent of unixtodos_filename. */
4048 for (p
= fname_copy
; *p
; p
= CharNext (p
))
4052 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
4054 DWORD w32err
= GetLastError ();
4058 case ERROR_INVALID_NAME
:
4059 case ERROR_BAD_PATHNAME
:
4060 case ERROR_FILE_NOT_FOUND
:
4061 case ERROR_BAD_NETPATH
:
4070 if ((mode
& X_OK
) != 0
4071 && !(is_exec (fname_copy
)
4072 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4077 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4082 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4090 /* Shadow some MSVC runtime functions to map requests for long filenames
4091 to reasonable short names if necessary. This was originally added to
4092 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4096 sys_chdir (const char * path
)
4098 path
= map_w32_filename (path
, NULL
);
4099 if (w32_unicode_filenames
)
4101 wchar_t newdir_w
[MAX_PATH
];
4103 if (filename_to_utf16 (path
, newdir_w
) == 0)
4104 return _wchdir (newdir_w
);
4109 char newdir_a
[MAX_PATH
];
4111 if (filename_to_ansi (path
, newdir_a
) == 0)
4112 return _chdir (newdir_a
);
4118 sys_chmod (const char * path
, int mode
)
4120 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4121 if (w32_unicode_filenames
)
4123 wchar_t path_w
[MAX_PATH
];
4125 filename_to_utf16 (path
, path_w
);
4126 return _wchmod (path_w
, mode
);
4130 char path_a
[MAX_PATH
];
4132 filename_to_ansi (path
, path_a
);
4133 return _chmod (path_a
, mode
);
4138 sys_creat (const char * path
, int mode
)
4140 path
= map_w32_filename (path
, NULL
);
4141 if (w32_unicode_filenames
)
4143 wchar_t path_w
[MAX_PATH
];
4145 filename_to_utf16 (path
, path_w
);
4146 return _wcreat (path_w
, mode
);
4150 char path_a
[MAX_PATH
];
4152 filename_to_ansi (path
, path_a
);
4153 return _creat (path_a
, mode
);
4158 sys_fopen (const char * path
, const char * mode
)
4162 const char * mode_save
= mode
;
4164 /* Force all file handles to be non-inheritable. This is necessary to
4165 ensure child processes don't unwittingly inherit handles that might
4166 prevent future file access. */
4170 else if (mode
[0] == 'w' || mode
[0] == 'a')
4171 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4175 /* Only do simplistic option parsing. */
4179 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4182 else if (mode
[0] == 'b')
4187 else if (mode
[0] == 't')
4194 path
= map_w32_filename (path
, NULL
);
4195 if (w32_unicode_filenames
)
4197 wchar_t path_w
[MAX_PATH
];
4199 filename_to_utf16 (path
, path_w
);
4200 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4204 char path_a
[MAX_PATH
];
4206 filename_to_ansi (path
, path_a
);
4207 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4212 return _fdopen (fd
, mode_save
);
4215 /* This only works on NTFS volumes, but is useful to have. */
4217 sys_link (const char * old
, const char * new)
4221 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4222 wchar_t oldname_w
[MAX_PATH
];
4223 char oldname_a
[MAX_PATH
];
4225 if (old
== NULL
|| new == NULL
)
4231 strcpy (oldname
, map_w32_filename (old
, NULL
));
4232 strcpy (newname
, map_w32_filename (new, NULL
));
4234 if (w32_unicode_filenames
)
4236 filename_to_utf16 (oldname
, oldname_w
);
4237 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4238 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4242 filename_to_ansi (oldname
, oldname_a
);
4243 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4244 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4246 if (fileh
!= INVALID_HANDLE_VALUE
)
4250 /* Confusingly, the "alternate" stream name field does not apply
4251 when restoring a hard link, and instead contains the actual
4252 stream data for the link (ie. the name of the link to create).
4253 The WIN32_STREAM_ID structure before the cStreamName field is
4254 the stream header, which is then immediately followed by the
4258 WIN32_STREAM_ID wid
;
4259 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4262 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4263 indicates that flag is unsupported for CP_UTF8, and OTOH says
4264 it is the default anyway. */
4265 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4266 data
.wid
.cStreamName
, MAX_PATH
);
4269 LPVOID context
= NULL
;
4272 data
.wid
.dwStreamId
= BACKUP_LINK
;
4273 data
.wid
.dwStreamAttributes
= 0;
4274 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4275 data
.wid
.Size
.HighPart
= 0;
4276 data
.wid
.dwStreamNameSize
= 0;
4278 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4279 offsetof (WIN32_STREAM_ID
, cStreamName
)
4280 + data
.wid
.Size
.LowPart
,
4281 &wbytes
, FALSE
, FALSE
, &context
)
4282 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4289 DWORD err
= GetLastError ();
4294 case ERROR_ACCESS_DENIED
:
4295 /* This is what happens when OLDNAME is a directory,
4296 since Windows doesn't support hard links to
4297 directories. Posix says to set errno to EPERM in
4299 if (w32_unicode_filenames
)
4300 attributes
= GetFileAttributesW (oldname_w
);
4302 attributes
= GetFileAttributesA (oldname_a
);
4303 if (attributes
!= -1
4304 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4306 else if (attributes
== -1
4307 && is_unc_volume (oldname
)
4308 && unc_volume_file_attributes (oldname
) != -1)
4313 case ERROR_TOO_MANY_LINKS
:
4316 case ERROR_NOT_SAME_DEVICE
:
4326 CloseHandle (fileh
);
4335 sys_mkdir (const char * path
)
4337 path
= map_w32_filename (path
, NULL
);
4339 if (w32_unicode_filenames
)
4341 wchar_t path_w
[MAX_PATH
];
4343 filename_to_utf16 (path
, path_w
);
4344 return _wmkdir (path_w
);
4348 char path_a
[MAX_PATH
];
4350 filename_to_ansi (path
, path_a
);
4351 return _mkdir (path_a
);
4356 sys_open (const char * path
, int oflag
, int mode
)
4358 const char* mpath
= map_w32_filename (path
, NULL
);
4361 if (w32_unicode_filenames
)
4363 wchar_t mpath_w
[MAX_PATH
];
4365 filename_to_utf16 (mpath
, mpath_w
);
4366 /* If possible, try to open file without _O_CREAT, to be able to
4367 write to existing hidden and system files. Force all file
4368 handles to be non-inheritable. */
4369 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4370 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4372 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4376 char mpath_a
[MAX_PATH
];
4378 filename_to_ansi (mpath
, mpath_a
);
4379 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4380 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4382 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4388 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4391 Standard algorithm for generating a temporary file name seems to be
4392 use pid or tid with a letter on the front (in place of the 6 X's)
4393 and cycle through the letters to find a unique name. We extend
4394 that to allow any reasonable character as the first of the 6 X's,
4395 so that the number of simultaneously used temporary files will be
4399 mkostemp (char * template, int flags
)
4403 unsigned uid
= GetCurrentThreadId ();
4404 int save_errno
= errno
;
4405 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4408 if (template == NULL
)
4411 p
= template + strlen (template);
4413 /* replace up to the last 5 X's with uid in decimal */
4414 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4416 p
[0] = '0' + uid
% 10;
4420 if (i
< 0 && p
[0] == 'X')
4425 p
[0] = first_char
[i
];
4426 if ((fd
= sys_open (template,
4427 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4428 S_IRUSR
| S_IWUSR
)) >= 0
4436 while (++i
< sizeof (first_char
));
4439 /* Template is badly formed or else we can't generate a unique name. */
4444 fchmod (int fd
, mode_t mode
)
4450 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4453 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4456 bool have_temp_a
= false;
4458 /* MoveFile on Windows 95 doesn't correctly change the short file name
4459 alias in a number of circumstances (it is not easy to predict when
4460 just by looking at oldname and newname, unfortunately). In these
4461 cases, renaming through a temporary name avoids the problem.
4463 A second problem on Windows 95 is that renaming through a temp name when
4464 newname is uppercase fails (the final long name ends up in
4465 lowercase, although the short alias might be uppercase) UNLESS the
4466 long temp name is not 8.3.
4468 So, on Windows 95 we always rename through a temp name, and we make sure
4469 the temp name has a long extension to ensure correct renaming. */
4471 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4473 /* volume_info is set indirectly by map_w32_filename. */
4474 oldname_dev
= volume_info
.serialnum
;
4476 if (os_subtype
== OS_9X
)
4481 char oldname_a
[MAX_PATH
];
4483 oldname
= map_w32_filename (oldname
, NULL
);
4484 filename_to_ansi (oldname
, oldname_a
);
4485 filename_to_ansi (temp
, temp_a
);
4486 if ((o
= strrchr (oldname_a
, '\\')))
4489 o
= (char *) oldname_a
;
4491 if ((p
= strrchr (temp_a
, '\\')))
4498 /* Force temp name to require a manufactured 8.3 alias - this
4499 seems to make the second rename work properly. */
4500 sprintf (p
, "_.%s.%d", o
, i
);
4502 result
= rename (oldname_a
, temp_a
);
4504 /* This loop must surely terminate! */
4505 while (result
< 0 && errno
== EEXIST
);
4511 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4512 (at least if it is a file; don't do this for directories).
4514 Since we mustn't do this if we are just changing the case of the
4515 file name (we would end up deleting the file we are trying to
4516 rename!), we let rename detect if the destination file already
4517 exists - that way we avoid the possible pitfalls of trying to
4518 determine ourselves whether two names really refer to the same
4519 file, which is not always possible in the general case. (Consider
4520 all the permutations of shared or subst'd drives, etc.) */
4522 newname
= map_w32_filename (newname
, NULL
);
4524 /* volume_info is set indirectly by map_w32_filename. */
4525 newname_dev
= volume_info
.serialnum
;
4527 if (w32_unicode_filenames
)
4529 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4531 filename_to_utf16 (temp
, temp_w
);
4532 filename_to_utf16 (newname
, newname_w
);
4533 result
= _wrename (temp_w
, newname_w
);
4534 if (result
< 0 && force
)
4536 DWORD w32err
= GetLastError ();
4539 && newname_dev
!= oldname_dev
)
4541 /* The implementation of `rename' on Windows does not return
4542 errno = EXDEV when you are moving a directory to a
4543 different storage device (ex. logical disk). It returns
4544 EACCES instead. So here we handle such situations and
4548 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4549 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4552 else if (errno
== EEXIST
)
4554 if (_wchmod (newname_w
, 0666) != 0)
4556 if (_wunlink (newname_w
) != 0)
4558 result
= _wrename (temp_w
, newname_w
);
4560 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4561 && is_symlink (temp
))
4563 /* This is Windows prohibiting the user from creating a
4564 symlink in another place, since that requires
4572 char newname_a
[MAX_PATH
];
4575 filename_to_ansi (temp
, temp_a
);
4576 filename_to_ansi (newname
, newname_a
);
4577 result
= rename (temp_a
, newname_a
);
4578 if (result
< 0 && force
)
4580 DWORD w32err
= GetLastError ();
4583 && newname_dev
!= oldname_dev
)
4587 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4588 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4591 else if (errno
== EEXIST
)
4593 if (_chmod (newname_a
, 0666) != 0)
4595 if (_unlink (newname_a
) != 0)
4597 result
= rename (temp_a
, newname_a
);
4599 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4600 && is_symlink (temp
))
4609 sys_rename (char const *old
, char const *new)
4611 return sys_rename_replace (old
, new, TRUE
);
4615 sys_rmdir (const char * path
)
4617 path
= map_w32_filename (path
, NULL
);
4619 if (w32_unicode_filenames
)
4621 wchar_t path_w
[MAX_PATH
];
4623 filename_to_utf16 (path
, path_w
);
4624 return _wrmdir (path_w
);
4628 char path_a
[MAX_PATH
];
4630 filename_to_ansi (path
, path_a
);
4631 return _rmdir (path_a
);
4636 sys_unlink (const char * path
)
4640 path
= map_w32_filename (path
, NULL
);
4642 if (w32_unicode_filenames
)
4644 wchar_t path_w
[MAX_PATH
];
4646 filename_to_utf16 (path
, path_w
);
4647 /* On Unix, unlink works without write permission. */
4648 _wchmod (path_w
, 0666);
4649 rmstatus
= _wunlink (path_w
);
4651 /* Symlinks to directories can only be deleted by _rmdir;
4652 _unlink returns EACCES. */
4655 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4656 rmstatus
= _wrmdir (path_w
);
4662 char path_a
[MAX_PATH
];
4664 filename_to_ansi (path
, path_a
);
4665 _chmod (path_a
, 0666);
4666 rmstatus
= _unlink (path_a
);
4670 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4671 rmstatus
= _rmdir (path_a
);
4679 static FILETIME utc_base_ft
;
4680 static ULONGLONG utc_base
; /* In 100ns units */
4681 static int init
= 0;
4683 #define FILETIME_TO_U64(result, ft) \
4685 ULARGE_INTEGER uiTemp; \
4686 uiTemp.LowPart = (ft).dwLowDateTime; \
4687 uiTemp.HighPart = (ft).dwHighDateTime; \
4688 result = uiTemp.QuadPart; \
4692 initialize_utc_base (void)
4694 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4703 st
.wMilliseconds
= 0;
4705 SystemTimeToFileTime (&st
, &utc_base_ft
);
4706 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4710 convert_time (FILETIME ft
)
4716 initialize_utc_base ();
4720 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4723 FILETIME_TO_U64 (tmp
, ft
);
4724 return (time_t) ((tmp
- utc_base
) / 10000000L);
4728 convert_from_time_t (time_t time
, FILETIME
* pft
)
4734 initialize_utc_base ();
4738 /* time in 100ns units since 1-Jan-1601 */
4739 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4740 pft
->dwHighDateTime
= tmp
.HighPart
;
4741 pft
->dwLowDateTime
= tmp
.LowPart
;
4744 static PSECURITY_DESCRIPTOR
4745 get_file_security_desc_by_handle (HANDLE h
)
4747 PSECURITY_DESCRIPTOR psd
= NULL
;
4749 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4750 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4752 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4753 NULL
, NULL
, NULL
, NULL
, &psd
);
4754 if (err
!= ERROR_SUCCESS
)
4760 static PSECURITY_DESCRIPTOR
4761 get_file_security_desc_by_name (const char *fname
)
4763 PSECURITY_DESCRIPTOR psd
= NULL
;
4765 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4766 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4768 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4770 err
= GetLastError ();
4771 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4775 psd
= xmalloc (sd_len
);
4776 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4788 unsigned n_subauthorities
;
4790 /* Use the last sub-authority value of the RID, the relative
4791 portion of the SID, as user/group ID. */
4792 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4793 if (n_subauthorities
< 1)
4794 return 0; /* the "World" RID */
4795 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4798 /* Caching SID and account values for faster lokup. */
4802 struct w32_id
*next
;
4804 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4807 static struct w32_id
*w32_idlist
;
4810 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4812 struct w32_id
*tail
, *found
;
4814 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4816 if (equal_sid ((PSID
)tail
->sid
, sid
))
4825 strcpy (name
, found
->name
);
4833 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4836 struct w32_id
*new_entry
;
4838 /* We don't want to leave behind stale cache from when Emacs was
4842 sid_len
= get_length_sid (sid
);
4843 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4846 new_entry
->rid
= id
;
4847 strcpy (new_entry
->name
, name
);
4848 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4849 new_entry
->next
= w32_idlist
;
4850 w32_idlist
= new_entry
;
4859 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4863 SID_NAME_USE ignore
;
4865 DWORD name_len
= sizeof (name
);
4867 DWORD domain_len
= sizeof (domain
);
4872 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4873 else if (what
== GID
)
4874 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4878 if (!result
|| !is_valid_sid (sid
))
4880 else if (!w32_cached_id (sid
, id
, nm
))
4882 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4883 domain
, &domain_len
, &ignore
)
4884 || name_len
> UNLEN
+1)
4888 *id
= get_rid (sid
);
4890 w32_add_to_cache (sid
, *id
, name
);
4897 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4899 int dflt_usr
= 0, dflt_grp
= 0;
4908 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4910 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4913 /* Consider files to belong to current user/group, if we cannot get
4914 more accurate information. */
4917 st
->st_uid
= dflt_passwd
.pw_uid
;
4918 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4922 st
->st_gid
= dflt_passwd
.pw_gid
;
4923 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4927 /* Return non-zero if NAME is a potentially slow filesystem. */
4928 int is_slow_fs (const char *);
4931 is_slow_fs (const char *name
)
4936 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4937 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4938 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4939 devtype
= GetDriveType (NULL
); /* use root of current drive */
4942 /* GetDriveType needs the root directory of the drive. */
4943 strncpy (drive_root
, name
, 2);
4944 drive_root
[2] = '\\';
4945 drive_root
[3] = '\0';
4946 devtype
= GetDriveType (drive_root
);
4948 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4951 /* If this is non-zero, the caller wants accurate information about
4952 file's owner and group, which could be expensive to get. dired.c
4953 uses this flag when needed for the job at hand. */
4954 int w32_stat_get_owner_group
;
4956 /* MSVC stat function can't cope with UNC names and has other bugs, so
4957 replace it with our own. This also allows us to calculate consistent
4958 inode values and owner/group without hacks in the main Emacs code,
4959 and support file names encoded in UTF-8. */
4962 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4964 char *name
, *save_name
, *r
;
4965 WIN32_FIND_DATAW wfd_w
;
4966 WIN32_FIND_DATAA wfd_a
;
4968 unsigned __int64 fake_inode
= 0;
4971 int rootdir
= FALSE
;
4972 PSECURITY_DESCRIPTOR psd
= NULL
;
4973 int is_a_symlink
= 0;
4974 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4975 DWORD access_rights
= 0;
4976 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4977 FILETIME ctime
, atime
, wtime
;
4978 wchar_t name_w
[MAX_PATH
];
4979 char name_a
[MAX_PATH
];
4981 if (path
== NULL
|| buf
== NULL
)
4987 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4988 /* Must be valid filename, no wild cards or other invalid
4990 if (strpbrk (name
, "*?|<>\""))
4996 len
= strlen (name
);
4997 /* Allocate 1 extra byte so that we could append a slash to a root
4998 directory, down below. */
4999 name
= strcpy (alloca (len
+ 2), name
);
5001 /* Avoid a somewhat costly call to is_symlink if the filesystem
5002 doesn't support symlinks. */
5003 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5004 is_a_symlink
= is_symlink (name
);
5006 /* Plan A: Open the file and get all the necessary information via
5007 the resulting handle. This solves several issues in one blow:
5009 . retrieves attributes for the target of a symlink, if needed
5010 . gets attributes of root directories and symlinks pointing to
5011 root directories, thus avoiding the need for special-casing
5012 these and detecting them by examining the file-name format
5013 . retrieves more accurate attributes (e.g., non-zero size for
5014 some directories, esp. directories that are junction points)
5015 . correctly resolves "c:/..", "/.." and similar file names
5016 . avoids run-time penalties for 99% of use cases
5018 Plan A is always tried first, unless the user asked not to (but
5019 if the file is a symlink and we need to follow links, we try Plan
5020 A even if the user asked not to).
5022 If Plan A fails, we go to Plan B (below), where various
5023 potentially expensive techniques must be used to handle "special"
5024 files such as UNC volumes etc. */
5025 if (!(NILP (Vw32_get_true_file_attributes
)
5026 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
5027 /* Following symlinks requires getting the info by handle. */
5028 || (is_a_symlink
&& follow_symlinks
))
5030 BY_HANDLE_FILE_INFORMATION info
;
5032 if (is_a_symlink
&& !follow_symlinks
)
5033 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
5034 /* READ_CONTROL access rights are required to get security info
5035 by handle. But if the OS doesn't support security in the
5036 first place, we don't need to try. */
5037 if (is_windows_9x () != TRUE
)
5038 access_rights
|= READ_CONTROL
;
5040 if (w32_unicode_filenames
)
5042 filename_to_utf16 (name
, name_w
);
5043 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5045 /* If CreateFile fails with READ_CONTROL, try again with
5046 zero as access rights. */
5047 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5048 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
5053 filename_to_ansi (name
, name_a
);
5054 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5056 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5057 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
5060 if (fh
== INVALID_HANDLE_VALUE
)
5061 goto no_true_file_attributes
;
5063 /* This is more accurate in terms of getting the correct number
5064 of links, but is quite slow (it is noticeable when Emacs is
5065 making a list of file name completions). */
5066 if (GetFileInformationByHandle (fh
, &info
))
5068 nlinks
= info
.nNumberOfLinks
;
5069 /* Might as well use file index to fake inode values, but this
5070 is not guaranteed to be unique unless we keep a handle open
5071 all the time (even then there are situations where it is
5072 not unique). Reputedly, there are at most 48 bits of info
5073 (on NTFS, presumably less on FAT). */
5074 fake_inode
= info
.nFileIndexHigh
;
5076 fake_inode
+= info
.nFileIndexLow
;
5077 serialnum
= info
.dwVolumeSerialNumber
;
5078 fs_high
= info
.nFileSizeHigh
;
5079 fs_low
= info
.nFileSizeLow
;
5080 ctime
= info
.ftCreationTime
;
5081 atime
= info
.ftLastAccessTime
;
5082 wtime
= info
.ftLastWriteTime
;
5083 fattrs
= info
.dwFileAttributes
;
5087 /* We don't go to Plan B here, because it's not clear that
5088 it's a good idea. The only known use case where
5089 CreateFile succeeds, but GetFileInformationByHandle fails
5090 (with ERROR_INVALID_FUNCTION) is for character devices
5091 such as NUL, PRN, etc. For these, switching to Plan B is
5092 a net loss, because we lose the character device
5093 attribute returned by GetFileType below (FindFirstFile
5094 doesn't set that bit in the attributes), and the other
5095 fields don't make sense for character devices anyway.
5096 Emacs doesn't really care for non-file entities in the
5097 context of l?stat, so neither do we. */
5099 /* w32err is assigned so one could put a breakpoint here and
5100 examine its value, when GetFileInformationByHandle
5102 DWORD w32err
= GetLastError ();
5106 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5112 /* Test for a symlink before testing for a directory, since
5113 symlinks to directories have the directory bit set, but we
5114 don't want them to appear as directories. */
5115 if (is_a_symlink
&& !follow_symlinks
)
5116 buf
->st_mode
= S_IFLNK
;
5117 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5118 buf
->st_mode
= S_IFDIR
;
5121 DWORD ftype
= GetFileType (fh
);
5125 case FILE_TYPE_DISK
:
5126 buf
->st_mode
= S_IFREG
;
5128 case FILE_TYPE_PIPE
:
5129 buf
->st_mode
= S_IFIFO
;
5131 case FILE_TYPE_CHAR
:
5132 case FILE_TYPE_UNKNOWN
:
5134 buf
->st_mode
= S_IFCHR
;
5137 /* We produce the fallback owner and group data, based on the
5138 current user that runs Emacs, in the following cases:
5140 . caller didn't request owner and group info
5141 . this is Windows 9X
5142 . getting security by handle failed, and we need to produce
5143 information for the target of a symlink (this is better
5144 than producing a potentially misleading info about the
5147 If getting security by handle fails, and we don't need to
5148 resolve symlinks, we try getting security by name. */
5149 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5150 get_file_owner_and_group (NULL
, buf
);
5153 psd
= get_file_security_desc_by_handle (fh
);
5156 get_file_owner_and_group (psd
, buf
);
5159 else if (!(is_a_symlink
&& follow_symlinks
))
5161 psd
= get_file_security_desc_by_name (name
);
5162 get_file_owner_and_group (psd
, buf
);
5166 get_file_owner_and_group (NULL
, buf
);
5172 no_true_file_attributes
:
5173 /* Plan B: Either getting a handle on the file failed, or the
5174 caller explicitly asked us to not bother making this
5175 information more accurate.
5177 Implementation note: In Plan B, we never bother to resolve
5178 symlinks, even if we got here because we tried Plan A and
5179 failed. That's because, even if the caller asked for extra
5180 precision by setting Vw32_get_true_file_attributes to t,
5181 resolving symlinks requires acquiring a file handle to the
5182 symlink, which we already know will fail. And if the user
5183 did not ask for extra precision, resolving symlinks will fly
5184 in the face of that request, since the user then wants the
5185 lightweight version of the code. */
5186 rootdir
= (path
>= save_name
+ len
- 1
5187 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5189 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5190 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5191 if (IS_DIRECTORY_SEP (r
[0])
5192 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5195 /* Note: If NAME is a symlink to the root of a UNC volume
5196 (i.e. "\\SERVER"), we will not detect that here, and we will
5197 return data about the symlink as result of FindFirst below.
5198 This is unfortunate, but that marginal use case does not
5199 justify a call to chase_symlinks which would impose a penalty
5200 on all the other use cases. (We get here for symlinks to
5201 roots of UNC volumes because CreateFile above fails for them,
5202 unlike with symlinks to root directories X:\ of drives.) */
5203 if (is_unc_volume (name
))
5205 fattrs
= unc_volume_file_attributes (name
);
5209 ctime
= atime
= wtime
= utc_base_ft
;
5213 /* Make sure root directories end in a slash. */
5214 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5215 strcpy (name
+ len
, "\\");
5216 if (GetDriveType (name
) < 2)
5222 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5223 ctime
= atime
= wtime
= utc_base_ft
;
5229 /* Make sure non-root directories do NOT end in a slash,
5230 otherwise FindFirstFile might fail. */
5231 if (IS_DIRECTORY_SEP (name
[len
-1]))
5234 /* (This is hacky, but helps when doing file completions on
5235 network drives.) Optimize by using information available from
5236 active readdir if possible. */
5237 len
= strlen (dir_pathname
);
5238 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5240 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5241 && last_dir_find_data
!= -1
5242 && !(is_a_symlink
&& follow_symlinks
)
5243 /* The 2 file-name comparisons below support only ASCII
5244 characters, and will lose (compare not equal) when
5245 the file names include non-ASCII characters that are
5246 the same but for the case. However, doing this
5247 properly involves: (a) converting both file names to
5248 UTF-16, (b) lower-casing both names using CharLowerW,
5249 and (c) comparing the results; this would be quite a
5250 bit slower, whereas Plan B is for users who want
5251 lightweight albeit inaccurate version of 'stat'. */
5252 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5253 && IS_DIRECTORY_SEP (name
[len
])
5254 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5256 have_wfd
= last_dir_find_data
;
5257 /* This was the last entry returned by readdir. */
5258 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5259 wfd_w
= dir_find_data_w
;
5261 wfd_a
= dir_find_data_a
;
5265 logon_network_drive (name
);
5267 if (w32_unicode_filenames
)
5269 filename_to_utf16 (name
, name_w
);
5270 fh
= FindFirstFileW (name_w
, &wfd_w
);
5271 have_wfd
= DIR_FIND_DATA_W
;
5275 filename_to_ansi (name
, name_a
);
5276 /* If NAME includes characters not representable by
5277 the current ANSI codepage, filename_to_ansi
5278 usually replaces them with a '?'. We don't want
5279 to let FindFirstFileA interpret those as wildcards,
5280 and "succeed", returning us data from some random
5281 file in the same directory. */
5282 if (_mbspbrk (name_a
, "?"))
5283 fh
= INVALID_HANDLE_VALUE
;
5285 fh
= FindFirstFileA (name_a
, &wfd_a
);
5286 have_wfd
= DIR_FIND_DATA_A
;
5288 if (fh
== INVALID_HANDLE_VALUE
)
5295 /* Note: if NAME is a symlink, the information we get from
5296 FindFirstFile is for the symlink, not its target. */
5297 if (have_wfd
== DIR_FIND_DATA_W
)
5299 fattrs
= wfd_w
.dwFileAttributes
;
5300 ctime
= wfd_w
.ftCreationTime
;
5301 atime
= wfd_w
.ftLastAccessTime
;
5302 wtime
= wfd_w
.ftLastWriteTime
;
5303 fs_high
= wfd_w
.nFileSizeHigh
;
5304 fs_low
= wfd_w
.nFileSizeLow
;
5308 fattrs
= wfd_a
.dwFileAttributes
;
5309 ctime
= wfd_a
.ftCreationTime
;
5310 atime
= wfd_a
.ftLastAccessTime
;
5311 wtime
= wfd_a
.ftLastWriteTime
;
5312 fs_high
= wfd_a
.nFileSizeHigh
;
5313 fs_low
= wfd_a
.nFileSizeLow
;
5317 serialnum
= volume_info
.serialnum
;
5319 if (is_a_symlink
&& !follow_symlinks
)
5320 buf
->st_mode
= S_IFLNK
;
5321 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5322 buf
->st_mode
= S_IFDIR
;
5324 buf
->st_mode
= S_IFREG
;
5326 get_file_owner_and_group (NULL
, buf
);
5329 buf
->st_ino
= fake_inode
;
5331 buf
->st_dev
= serialnum
;
5332 buf
->st_rdev
= serialnum
;
5334 buf
->st_size
= fs_high
;
5335 buf
->st_size
<<= 32;
5336 buf
->st_size
+= fs_low
;
5337 buf
->st_nlink
= nlinks
;
5339 /* Convert timestamps to Unix format. */
5340 buf
->st_mtime
= convert_time (wtime
);
5341 buf
->st_atime
= convert_time (atime
);
5342 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5343 buf
->st_ctime
= convert_time (ctime
);
5344 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5346 /* determine rwx permissions */
5347 if (is_a_symlink
&& !follow_symlinks
)
5348 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5351 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5352 permission
= S_IREAD
;
5354 permission
= S_IREAD
| S_IWRITE
;
5356 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5357 permission
|= S_IEXEC
;
5358 else if (is_exec (name
))
5359 permission
|= S_IEXEC
;
5362 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5368 stat (const char * path
, struct stat
* buf
)
5370 return stat_worker (path
, buf
, 1);
5374 lstat (const char * path
, struct stat
* buf
)
5376 return stat_worker (path
, buf
, 0);
5380 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5382 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5383 This is good enough for the current usage in Emacs, but is fragile.
5385 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5386 Gnulib does this and can serve as a model. */
5387 char fullname
[MAX_UTF8_PATH
];
5391 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5393 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5394 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5397 errno
= ENAMETOOLONG
;
5403 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5406 /* Provide fstat and utime as well as stat for consistent handling of
5409 fstat (int desc
, struct stat
* buf
)
5411 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5412 BY_HANDLE_FILE_INFORMATION info
;
5413 unsigned __int64 fake_inode
;
5416 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5418 case FILE_TYPE_DISK
:
5419 buf
->st_mode
= S_IFREG
;
5420 if (!GetFileInformationByHandle (fh
, &info
))
5426 case FILE_TYPE_PIPE
:
5427 buf
->st_mode
= S_IFIFO
;
5429 case FILE_TYPE_CHAR
:
5430 case FILE_TYPE_UNKNOWN
:
5432 buf
->st_mode
= S_IFCHR
;
5434 memset (&info
, 0, sizeof (info
));
5435 info
.dwFileAttributes
= 0;
5436 info
.ftCreationTime
= utc_base_ft
;
5437 info
.ftLastAccessTime
= utc_base_ft
;
5438 info
.ftLastWriteTime
= utc_base_ft
;
5441 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5442 buf
->st_mode
= S_IFDIR
;
5444 buf
->st_nlink
= info
.nNumberOfLinks
;
5445 /* Might as well use file index to fake inode values, but this
5446 is not guaranteed to be unique unless we keep a handle open
5447 all the time (even then there are situations where it is
5448 not unique). Reputedly, there are at most 48 bits of info
5449 (on NTFS, presumably less on FAT). */
5450 fake_inode
= info
.nFileIndexHigh
;
5452 fake_inode
+= info
.nFileIndexLow
;
5454 /* MSVC defines _ino_t to be short; other libc's might not. */
5455 if (sizeof (buf
->st_ino
) == 2)
5456 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5458 buf
->st_ino
= fake_inode
;
5460 /* If the caller so requested, get the true file owner and group.
5461 Otherwise, consider the file to belong to the current user. */
5462 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5463 get_file_owner_and_group (NULL
, buf
);
5466 PSECURITY_DESCRIPTOR psd
= NULL
;
5468 psd
= get_file_security_desc_by_handle (fh
);
5471 get_file_owner_and_group (psd
, buf
);
5475 get_file_owner_and_group (NULL
, buf
);
5478 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5479 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5481 buf
->st_size
= info
.nFileSizeHigh
;
5482 buf
->st_size
<<= 32;
5483 buf
->st_size
+= info
.nFileSizeLow
;
5485 /* Convert timestamps to Unix format. */
5486 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5487 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5488 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5489 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5490 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5492 /* determine rwx permissions */
5493 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5494 permission
= S_IREAD
;
5496 permission
= S_IREAD
| S_IWRITE
;
5498 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5499 permission
|= S_IEXEC
;
5502 #if 0 /* no way of knowing the filename */
5503 char * p
= strrchr (name
, '.');
5505 (xstrcasecmp (p
, ".exe") == 0 ||
5506 xstrcasecmp (p
, ".com") == 0 ||
5507 xstrcasecmp (p
, ".bat") == 0 ||
5508 xstrcasecmp (p
, ".cmd") == 0))
5509 permission
|= S_IEXEC
;
5513 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5518 /* A version of 'utime' which handles directories as well as
5522 utime (const char *name
, struct utimbuf
*times
)
5524 struct utimbuf deftime
;
5531 deftime
.modtime
= deftime
.actime
= time (NULL
);
5535 if (w32_unicode_filenames
)
5537 wchar_t name_utf16
[MAX_PATH
];
5539 if (filename_to_utf16 (name
, name_utf16
) != 0)
5540 return -1; /* errno set by filename_to_utf16 */
5542 /* Need write access to set times. */
5543 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5544 /* If NAME specifies a directory, FILE_SHARE_DELETE
5545 allows other processes to delete files inside it,
5546 while we have the directory open. */
5547 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5548 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5552 char name_ansi
[MAX_PATH
];
5554 if (filename_to_ansi (name
, name_ansi
) != 0)
5555 return -1; /* errno set by filename_to_ansi */
5557 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5558 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5559 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5561 if (fh
!= INVALID_HANDLE_VALUE
)
5563 convert_from_time_t (times
->actime
, &atime
);
5564 convert_from_time_t (times
->modtime
, &mtime
);
5565 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5575 DWORD err
= GetLastError ();
5579 case ERROR_FILE_NOT_FOUND
:
5580 case ERROR_PATH_NOT_FOUND
:
5581 case ERROR_INVALID_DRIVE
:
5582 case ERROR_BAD_NETPATH
:
5583 case ERROR_DEV_NOT_EXIST
:
5584 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5585 file name includes ?s, i.e. translation to ANSI failed. */
5586 case ERROR_INVALID_NAME
:
5589 case ERROR_TOO_MANY_OPEN_FILES
:
5592 case ERROR_ACCESS_DENIED
:
5593 case ERROR_SHARING_VIOLATION
:
5606 sys_umask (int mode
)
5608 static int current_mask
;
5609 int retval
, arg
= 0;
5611 /* The only bit we really support is the write bit. Files are
5612 always readable on MS-Windows, and the execute bit does not exist
5614 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5615 to prevent access by other users on NTFS. */
5616 if ((mode
& S_IWRITE
) != 0)
5619 retval
= _umask (arg
);
5620 /* Merge into the return value the bits they've set the last time,
5621 which msvcrt.dll ignores and never returns. Emacs insists on its
5622 notion of mask being identical to what we return. */
5623 retval
|= (current_mask
& ~S_IWRITE
);
5624 current_mask
= mode
;
5630 /* Symlink-related functions. */
5631 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5632 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5636 symlink (char const *filename
, char const *linkname
)
5638 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5640 int dir_access
, filename_ends_in_slash
;
5642 /* Diagnostics follows Posix as much as possible. */
5643 if (filename
== NULL
|| linkname
== NULL
)
5653 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5655 errno
= ENAMETOOLONG
;
5659 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5660 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5666 /* Note: since empty FILENAME was already rejected, we can safely
5667 refer to FILENAME[1]. */
5668 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5670 /* Non-absolute FILENAME is understood as being relative to
5671 LINKNAME's directory. We need to prepend that directory to
5672 FILENAME to get correct results from faccessat below, since
5673 otherwise it will interpret FILENAME relative to the
5674 directory where the Emacs process runs. Note that
5675 make-symbolic-link always makes sure LINKNAME is a fully
5676 expanded file name. */
5677 char tem
[MAX_UTF8_PATH
];
5678 char *p
= linkfn
+ strlen (linkfn
);
5680 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5683 strncpy (tem
, linkfn
, p
- linkfn
);
5684 strcpy (tem
+ (p
- linkfn
), filename
);
5685 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5688 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5690 /* Since Windows distinguishes between symlinks to directories and
5691 to files, we provide a kludgy feature: if FILENAME doesn't
5692 exist, but ends in a slash, we create a symlink to directory. If
5693 FILENAME exists and is a directory, we always create a symlink to
5695 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5696 if (dir_access
== 0 || filename_ends_in_slash
)
5697 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5699 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5700 if (filename_ends_in_slash
)
5701 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5704 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5706 /* ENOSYS is set by create_symbolic_link, when it detects that
5707 the OS doesn't support the CreateSymbolicLink API. */
5708 if (errno
!= ENOSYS
)
5710 DWORD w32err
= GetLastError ();
5714 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5715 TGTFN point to the same file name, go figure. */
5717 case ERROR_FILE_EXISTS
:
5720 case ERROR_ACCESS_DENIED
:
5723 case ERROR_FILE_NOT_FOUND
:
5724 case ERROR_PATH_NOT_FOUND
:
5725 case ERROR_BAD_NETPATH
:
5726 case ERROR_INVALID_REPARSE_DATA
:
5729 case ERROR_DIRECTORY
:
5732 case ERROR_PRIVILEGE_NOT_HELD
:
5733 case ERROR_NOT_ALL_ASSIGNED
:
5736 case ERROR_DISK_FULL
:
5749 /* A quick inexpensive test of whether FILENAME identifies a file that
5750 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5751 must already be in the normalized form returned by
5752 map_w32_filename. If the symlink is to a directory, the
5753 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5755 Note: for repeated operations on many files, it is best to test
5756 whether the underlying volume actually supports symlinks, by
5757 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5758 avoid the call to this function if it doesn't. That's because the
5759 call to GetFileAttributes takes a non-negligible time, especially
5760 on non-local or removable filesystems. See stat_worker for an
5761 example of how to do that. */
5763 is_symlink (const char *filename
)
5766 wchar_t filename_w
[MAX_PATH
];
5767 char filename_a
[MAX_PATH
];
5768 WIN32_FIND_DATAW wfdw
;
5769 WIN32_FIND_DATAA wfda
;
5771 int attrs_mean_symlink
;
5773 if (w32_unicode_filenames
)
5775 filename_to_utf16 (filename
, filename_w
);
5776 attrs
= GetFileAttributesW (filename_w
);
5780 filename_to_ansi (filename
, filename_a
);
5781 attrs
= GetFileAttributesA (filename_a
);
5785 DWORD w32err
= GetLastError ();
5789 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5791 case ERROR_ACCESS_DENIED
:
5794 case ERROR_FILE_NOT_FOUND
:
5795 case ERROR_PATH_NOT_FOUND
:
5802 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5804 logon_network_drive (filename
);
5805 if (w32_unicode_filenames
)
5807 fh
= FindFirstFileW (filename_w
, &wfdw
);
5808 attrs_mean_symlink
=
5809 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5810 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5811 if (attrs_mean_symlink
)
5812 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5814 else if (_mbspbrk (filename_a
, "?"))
5816 /* filename_to_ansi failed to convert the file name. */
5822 fh
= FindFirstFileA (filename_a
, &wfda
);
5823 attrs_mean_symlink
=
5824 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5825 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5826 if (attrs_mean_symlink
)
5827 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5829 if (fh
== INVALID_HANDLE_VALUE
)
5832 return attrs_mean_symlink
;
5835 /* If NAME identifies a symbolic link, copy into BUF the file name of
5836 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5837 null-terminate the target name, even if it fits. Return the number
5838 of bytes copied, or -1 if NAME is not a symlink or any error was
5839 encountered while resolving it. The file name copied into BUF is
5840 encoded in the current ANSI codepage. */
5842 readlink (const char *name
, char *buf
, size_t buf_size
)
5845 TOKEN_PRIVILEGES privs
;
5846 int restore_privs
= 0;
5849 char resolved
[MAX_UTF8_PATH
];
5862 path
= map_w32_filename (name
, NULL
);
5864 if (strlen (path
) > MAX_UTF8_PATH
)
5866 errno
= ENAMETOOLONG
;
5871 if (is_windows_9x () == TRUE
5872 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5873 || !is_symlink (path
))
5876 errno
= EINVAL
; /* not a symlink */
5880 /* Done with simple tests, now we're in for some _real_ work. */
5881 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5883 /* Implementation note: From here and onward, don't return early,
5884 since that will fail to restore the original set of privileges of
5885 the calling thread. */
5887 retval
= -1; /* not too optimistic, are we? */
5889 /* Note: In the next call to CreateFile, we use zero as the 2nd
5890 argument because, when the symlink is a hidden/system file,
5891 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5892 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5893 and directory symlinks. */
5894 if (w32_unicode_filenames
)
5896 wchar_t path_w
[MAX_PATH
];
5898 filename_to_utf16 (path
, path_w
);
5899 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5900 FILE_FLAG_OPEN_REPARSE_POINT
5901 | FILE_FLAG_BACKUP_SEMANTICS
,
5906 char path_a
[MAX_PATH
];
5908 filename_to_ansi (path
, path_a
);
5909 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5910 FILE_FLAG_OPEN_REPARSE_POINT
5911 | FILE_FLAG_BACKUP_SEMANTICS
,
5914 if (sh
!= INVALID_HANDLE_VALUE
)
5916 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5917 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5920 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5921 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5924 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5928 /* Copy the link target name, in wide characters, from
5929 reparse_data, then convert it to multibyte encoding in
5930 the current locale's codepage. */
5934 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5936 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5937 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5938 size_t size_to_copy
= buf_size
;
5940 /* According to MSDN, PrintNameLength does not include the
5941 terminating null character. */
5942 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5943 memcpy (lwname
, lwname_src
, lwname_len
);
5944 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5945 filename_from_utf16 (lwname
, resolved
);
5946 dostounix_filename (resolved
);
5947 lname_size
= strlen (resolved
) + 1;
5948 if (lname_size
<= buf_size
)
5949 size_to_copy
= lname_size
;
5950 strncpy (buf
, resolved
, size_to_copy
);
5952 retval
= size_to_copy
;
5958 /* CreateFile failed. */
5959 DWORD w32err2
= GetLastError ();
5963 case ERROR_FILE_NOT_FOUND
:
5964 case ERROR_PATH_NOT_FOUND
:
5967 case ERROR_ACCESS_DENIED
:
5968 case ERROR_TOO_MANY_OPEN_FILES
:
5978 restore_privilege (&privs
);
5986 readlinkat (int fd
, char const *name
, char *buffer
,
5989 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5990 as in fstatat. FIXME: Add proper support for readlinkat. */
5991 char fullname
[MAX_UTF8_PATH
];
5995 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5998 errno
= ENAMETOOLONG
;
6004 return readlink (name
, buffer
, buffer_size
);
6007 /* If FILE is a symlink, return its target (stored in a static
6008 buffer); otherwise return FILE.
6010 This function repeatedly resolves symlinks in the last component of
6011 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6012 until it arrives at a file whose last component is not a symlink,
6013 or some error occurs. It returns the target of the last
6014 successfully resolved symlink in the chain. If it succeeds to
6015 resolve even a single symlink, the value returned is an absolute
6016 file name with backslashes (result of GetFullPathName). By
6017 contrast, if the original FILE is returned, it is unaltered.
6019 Note: This function can set errno even if it succeeds.
6021 Implementation note: we only resolve the last portion ("basename")
6022 of the argument FILE and of each following file in the chain,
6023 disregarding any possible symlinks in its leading directories.
6024 This is because Windows system calls and library functions
6025 transparently resolve symlinks in leading directories and return
6026 correct information, as long as the basename is not a symlink. */
6028 chase_symlinks (const char *file
)
6030 static char target
[MAX_UTF8_PATH
];
6031 char link
[MAX_UTF8_PATH
];
6032 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
6033 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
6034 ssize_t res
, link_len
;
6037 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
6038 return (char *)file
;
6040 if (w32_unicode_filenames
)
6042 wchar_t file_w
[MAX_PATH
];
6044 filename_to_utf16 (file
, file_w
);
6045 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
6046 return (char *)file
;
6047 filename_from_utf16 (link_w
, link
);
6051 char file_a
[MAX_PATH
];
6053 filename_to_ansi (file
, file_a
);
6054 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
6055 return (char *)file
;
6056 filename_from_ansi (link_a
, link
);
6058 link_len
= strlen (link
);
6063 /* Remove trailing slashes, as we want to resolve the last
6064 non-trivial part of the link name. */
6065 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
6066 link
[link_len
--] = '\0';
6068 res
= readlink (link
, target
, MAX_UTF8_PATH
);
6072 if (!(IS_DEVICE_SEP (target
[1])
6073 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
6075 /* Target is relative. Append it to the directory part of
6076 the symlink, then copy the result back to target. */
6077 char *p
= link
+ link_len
;
6079 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
6082 strcpy (target
, link
);
6084 /* Resolve any "." and ".." to get a fully-qualified file name
6086 if (w32_unicode_filenames
)
6088 filename_to_utf16 (target
, target_w
);
6089 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
6091 filename_from_utf16 (link_w
, link
);
6095 filename_to_ansi (target
, target_a
);
6096 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
6098 filename_from_ansi (link_a
, link
);
6100 link_len
= strlen (link
);
6102 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6104 if (loop_count
> 100)
6107 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6108 return (char *)file
;
6113 /* Posix ACL emulation. */
6116 acl_valid (acl_t acl
)
6118 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6122 acl_to_text (acl_t acl
, ssize_t
*size
)
6125 SECURITY_INFORMATION flags
=
6126 OWNER_SECURITY_INFORMATION
|
6127 GROUP_SECURITY_INFORMATION
|
6128 DACL_SECURITY_INFORMATION
;
6129 char *retval
= NULL
;
6135 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6138 /* We don't want to mix heaps, so we duplicate the string in our
6139 heap and free the one allocated by the API. */
6140 retval
= xstrdup (str_acl
);
6143 LocalFree (str_acl
);
6145 else if (errno
!= ENOTSUP
)
6152 acl_from_text (const char *acl_str
)
6154 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6160 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6163 retval
= xmalloc (sd_size
);
6164 memcpy (retval
, psd
, sd_size
);
6167 else if (errno
!= ENOTSUP
)
6174 acl_free (void *ptr
)
6181 acl_get_file (const char *fname
, acl_type_t type
)
6183 PSECURITY_DESCRIPTOR psd
= NULL
;
6184 const char *filename
;
6186 if (type
== ACL_TYPE_ACCESS
)
6189 SECURITY_INFORMATION si
=
6190 OWNER_SECURITY_INFORMATION
|
6191 GROUP_SECURITY_INFORMATION
|
6192 DACL_SECURITY_INFORMATION
;
6195 filename
= map_w32_filename (fname
, NULL
);
6196 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6197 fname
= chase_symlinks (filename
);
6202 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6203 && errno
!= ENOTSUP
)
6205 err
= GetLastError ();
6206 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6208 psd
= xmalloc (sd_len
);
6209 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6216 else if (err
== ERROR_FILE_NOT_FOUND
6217 || err
== ERROR_PATH_NOT_FOUND
6218 /* ERROR_INVALID_NAME is what we get if
6219 w32-unicode-filenames is nil and the file cannot
6220 be encoded in the current ANSI codepage. */
6221 || err
== ERROR_INVALID_NAME
)
6229 else if (type
!= ACL_TYPE_DEFAULT
)
6236 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6238 TOKEN_PRIVILEGES old1
, old2
;
6240 int st
= 0, retval
= -1;
6241 SECURITY_INFORMATION flags
= 0;
6242 PSID psidOwner
, psidGroup
;
6247 const char *filename
;
6249 if (acl_valid (acl
) != 0
6250 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6256 if (type
== ACL_TYPE_DEFAULT
)
6262 filename
= map_w32_filename (fname
, NULL
);
6263 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6264 fname
= chase_symlinks (filename
);
6268 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6271 flags
|= OWNER_SECURITY_INFORMATION
;
6272 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6275 flags
|= GROUP_SECURITY_INFORMATION
;
6276 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6279 flags
|= DACL_SECURITY_INFORMATION
;
6283 /* According to KB-245153, setting the owner will succeed if either:
6284 (1) the caller is the user who will be the new owner, and has the
6285 SE_TAKE_OWNERSHIP privilege, or
6286 (2) the caller has the SE_RESTORE privilege, in which case she can
6287 set any valid user or group as the owner
6289 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6290 privileges, and disregard any failures in obtaining them. If
6291 these privileges cannot be obtained, and do not already exist in
6292 the calling thread's security token, this function could fail
6294 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6296 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6301 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6302 DACL inheritance is involved, but it seems to preserve ownership
6303 better than SetNamedSecurityInfo, which is important e.g., in
6305 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6307 err
= GetLastError ();
6309 if (errno
!= ENOTSUP
)
6310 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6311 psidOwner
, psidGroup
, pacl
, NULL
);
6314 err
= ERROR_SUCCESS
;
6315 if (err
!= ERROR_SUCCESS
)
6317 if (errno
== ENOTSUP
)
6319 else if (err
== ERROR_INVALID_OWNER
6320 || err
== ERROR_NOT_ALL_ASSIGNED
6321 || err
== ERROR_ACCESS_DENIED
)
6323 /* Maybe the requested ACL and the one the file already has
6324 are identical, in which case we can silently ignore the
6325 failure. (And no, Windows doesn't.) */
6326 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6331 char *acl_from
= acl_to_text (current_acl
, NULL
);
6332 char *acl_to
= acl_to_text (acl
, NULL
);
6334 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6340 acl_free (acl_from
);
6343 acl_free (current_acl
);
6346 else if (err
== ERROR_FILE_NOT_FOUND
6347 || err
== ERROR_PATH_NOT_FOUND
6348 /* ERROR_INVALID_NAME is what we get if
6349 w32-unicode-filenames is nil and the file cannot be
6350 encoded in the current ANSI codepage. */
6351 || err
== ERROR_INVALID_NAME
)
6365 restore_privilege (&old2
);
6366 restore_privilege (&old1
);
6374 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6375 have a fixed max size for file names, so we don't need the kind of
6376 alloc/malloc/realloc dance the gnulib version does. We also don't
6377 support FD-relative symlinks. */
6379 careadlinkat (int fd
, char const *filename
,
6380 char *buffer
, size_t buffer_size
,
6381 struct allocator
const *alloc
,
6382 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6384 char linkname
[MAX_UTF8_PATH
];
6387 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6391 char *retval
= buffer
;
6393 linkname
[link_size
++] = '\0';
6394 if (link_size
> buffer_size
)
6395 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6397 memcpy (retval
, linkname
, link_size
);
6405 w32_copy_file (const char *from
, const char *to
,
6406 int keep_time
, int preserve_ownership
, int copy_acls
)
6410 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6411 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6413 /* We ignore preserve_ownership for now. */
6414 preserve_ownership
= preserve_ownership
;
6418 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6419 if (acl
== NULL
&& acl_errno_valid (errno
))
6422 if (w32_unicode_filenames
)
6424 filename_to_utf16 (from
, from_w
);
6425 filename_to_utf16 (to
, to_w
);
6426 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6430 filename_to_ansi (from
, from_a
);
6431 filename_to_ansi (to
, to_a
);
6432 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6436 /* CopyFile doesn't set errno when it fails. By far the most
6437 "popular" reason is that the target is read-only. */
6438 DWORD err
= GetLastError ();
6442 case ERROR_FILE_NOT_FOUND
:
6445 case ERROR_ACCESS_DENIED
:
6448 case ERROR_ENCRYPTION_FAILED
:
6460 /* CopyFile retains the timestamp by default. However, see
6461 "Community Additions" for CopyFile: it sounds like that is not
6462 entirely true. Testing on Windows XP confirms that modified time
6463 is copied, but creation and last-access times are not.
6465 else if (!keep_time
)
6467 struct timespec now
;
6470 if (w32_unicode_filenames
)
6472 /* Ensure file is writable while its times are set. */
6473 attributes
= GetFileAttributesW (to_w
);
6474 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6475 now
= current_timespec ();
6476 if (set_file_times (-1, to
, now
, now
))
6478 /* Restore original attributes. */
6479 SetFileAttributesW (to_w
, attributes
);
6484 /* Restore original attributes. */
6485 SetFileAttributesW (to_w
, attributes
);
6489 attributes
= GetFileAttributesA (to_a
);
6490 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6491 now
= current_timespec ();
6492 if (set_file_times (-1, to
, now
, now
))
6494 SetFileAttributesA (to_a
, attributes
);
6499 SetFileAttributesA (to_a
, attributes
);
6505 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6507 if (fail
&& acl_errno_valid (errno
))
6515 /* Support for browsing other processes and their attributes. See
6516 process.c for the Lisp bindings. */
6518 /* Helper wrapper functions. */
6520 static HANDLE WINAPI
6521 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6523 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6525 if (g_b_init_create_toolhelp32_snapshot
== 0)
6527 g_b_init_create_toolhelp32_snapshot
= 1;
6528 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6529 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6530 "CreateToolhelp32Snapshot");
6532 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6534 return INVALID_HANDLE_VALUE
;
6536 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6540 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6542 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6544 if (g_b_init_process32_first
== 0)
6546 g_b_init_process32_first
= 1;
6547 s_pfn_Process32_First
= (Process32First_Proc
)
6548 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6551 if (s_pfn_Process32_First
== NULL
)
6555 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6559 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6561 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6563 if (g_b_init_process32_next
== 0)
6565 g_b_init_process32_next
= 1;
6566 s_pfn_Process32_Next
= (Process32Next_Proc
)
6567 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6570 if (s_pfn_Process32_Next
== NULL
)
6574 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6578 open_thread_token (HANDLE ThreadHandle
,
6579 DWORD DesiredAccess
,
6581 PHANDLE TokenHandle
)
6583 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6584 HMODULE hm_advapi32
= NULL
;
6585 if (is_windows_9x () == TRUE
)
6587 SetLastError (ERROR_NOT_SUPPORTED
);
6590 if (g_b_init_open_thread_token
== 0)
6592 g_b_init_open_thread_token
= 1;
6593 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6594 s_pfn_Open_Thread_Token
=
6595 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6597 if (s_pfn_Open_Thread_Token
== NULL
)
6599 SetLastError (ERROR_NOT_SUPPORTED
);
6603 s_pfn_Open_Thread_Token (
6612 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6614 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6615 HMODULE hm_advapi32
= NULL
;
6616 if (is_windows_9x () == TRUE
)
6620 if (g_b_init_impersonate_self
== 0)
6622 g_b_init_impersonate_self
= 1;
6623 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6624 s_pfn_Impersonate_Self
=
6625 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6627 if (s_pfn_Impersonate_Self
== NULL
)
6631 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6635 revert_to_self (void)
6637 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6638 HMODULE hm_advapi32
= NULL
;
6639 if (is_windows_9x () == TRUE
)
6643 if (g_b_init_revert_to_self
== 0)
6645 g_b_init_revert_to_self
= 1;
6646 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6647 s_pfn_Revert_To_Self
=
6648 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6650 if (s_pfn_Revert_To_Self
== NULL
)
6654 return s_pfn_Revert_To_Self ();
6658 get_process_memory_info (HANDLE h_proc
,
6659 PPROCESS_MEMORY_COUNTERS mem_counters
,
6662 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6663 HMODULE hm_psapi
= NULL
;
6664 if (is_windows_9x () == TRUE
)
6668 if (g_b_init_get_process_memory_info
== 0)
6670 g_b_init_get_process_memory_info
= 1;
6671 hm_psapi
= LoadLibrary ("Psapi.dll");
6673 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6674 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6676 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6680 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6684 get_process_working_set_size (HANDLE h_proc
,
6688 static GetProcessWorkingSetSize_Proc
6689 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6691 if (is_windows_9x () == TRUE
)
6695 if (g_b_init_get_process_working_set_size
== 0)
6697 g_b_init_get_process_working_set_size
= 1;
6698 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6699 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6700 "GetProcessWorkingSetSize");
6702 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6706 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6710 global_memory_status (MEMORYSTATUS
*buf
)
6712 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6714 if (is_windows_9x () == TRUE
)
6718 if (g_b_init_global_memory_status
== 0)
6720 g_b_init_global_memory_status
= 1;
6721 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6722 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6723 "GlobalMemoryStatus");
6725 if (s_pfn_Global_Memory_Status
== NULL
)
6729 return s_pfn_Global_Memory_Status (buf
);
6733 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6735 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6737 if (is_windows_9x () == TRUE
)
6741 if (g_b_init_global_memory_status_ex
== 0)
6743 g_b_init_global_memory_status_ex
= 1;
6744 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6745 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6746 "GlobalMemoryStatusEx");
6748 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6752 return s_pfn_Global_Memory_Status_Ex (buf
);
6756 list_system_processes (void)
6758 Lisp_Object proclist
= Qnil
;
6761 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6763 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6765 PROCESSENTRY32 proc_entry
;
6769 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6770 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6771 res
= process32_next (h_snapshot
, &proc_entry
))
6773 proc_id
= proc_entry
.th32ProcessID
;
6774 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6777 CloseHandle (h_snapshot
);
6778 proclist
= Fnreverse (proclist
);
6785 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6787 TOKEN_PRIVILEGES priv
;
6788 DWORD priv_size
= sizeof (priv
);
6789 DWORD opriv_size
= sizeof (*old_priv
);
6790 HANDLE h_token
= NULL
;
6791 HANDLE h_thread
= GetCurrentThread ();
6795 res
= open_thread_token (h_thread
,
6796 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6798 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6800 if (impersonate_self (SecurityImpersonation
))
6801 res
= open_thread_token (h_thread
,
6802 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6807 priv
.PrivilegeCount
= 1;
6808 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6809 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6810 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6811 old_priv
, &opriv_size
)
6812 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6816 CloseHandle (h_token
);
6822 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6824 DWORD priv_size
= sizeof (*priv
);
6825 HANDLE h_token
= NULL
;
6828 if (open_thread_token (GetCurrentThread (),
6829 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6832 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6833 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6837 CloseHandle (h_token
);
6843 ltime (ULONGLONG time_100ns
)
6845 ULONGLONG time_sec
= time_100ns
/ 10000000;
6846 int subsec
= time_100ns
% 10000000;
6847 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6848 subsec
/ 10, subsec
% 10 * 100000);
6851 #define U64_TO_LISP_TIME(time) ltime (time)
6854 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6855 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6858 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6859 ULONGLONG tem1
, tem2
, tem3
, tem
;
6862 || !get_process_times_fn
6863 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6864 &ft_kernel
, &ft_user
))
6867 GetSystemTimeAsFileTime (&ft_current
);
6869 FILETIME_TO_U64 (tem1
, ft_kernel
);
6870 *stime
= U64_TO_LISP_TIME (tem1
);
6872 FILETIME_TO_U64 (tem2
, ft_user
);
6873 *utime
= U64_TO_LISP_TIME (tem2
);
6876 *ttime
= U64_TO_LISP_TIME (tem3
);
6878 FILETIME_TO_U64 (tem
, ft_creation
);
6879 /* Process no 4 (System) returns zero creation time. */
6882 *ctime
= U64_TO_LISP_TIME (tem
);
6886 FILETIME_TO_U64 (tem3
, ft_current
);
6887 tem
= (tem3
- utc_base
) - tem
;
6889 *etime
= U64_TO_LISP_TIME (tem
);
6893 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6904 system_process_attributes (Lisp_Object pid
)
6906 Lisp_Object attrs
= Qnil
;
6907 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6908 HANDLE h_snapshot
, h_proc
;
6911 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6912 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6913 DWORD glength
= sizeof (gname
);
6914 HANDLE token
= NULL
;
6915 SID_NAME_USE user_type
;
6916 unsigned char *buf
= NULL
;
6918 TOKEN_USER user_token
;
6919 TOKEN_PRIMARY_GROUP group_token
;
6922 PROCESS_MEMORY_COUNTERS mem
;
6923 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6924 SIZE_T minrss
, maxrss
;
6926 MEMORY_STATUS_EX memstex
;
6927 double totphys
= 0.0;
6928 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6930 BOOL result
= FALSE
;
6932 CHECK_NUMBER_OR_FLOAT (pid
);
6933 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6935 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6937 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6942 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6943 for (res
= process32_first (h_snapshot
, &pe
); res
;
6944 res
= process32_next (h_snapshot
, &pe
))
6946 if (proc_id
== pe
.th32ProcessID
)
6949 decoded_cmd
= build_string ("Idle");
6952 /* Decode the command name from locale-specific
6954 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6957 code_convert_string_norecord (cmd_str
,
6958 Vlocale_coding_system
, 0);
6960 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6961 attrs
= Fcons (Fcons (Qppid
,
6962 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6964 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6966 attrs
= Fcons (Fcons (Qthcount
,
6967 make_fixnum_or_float (pe
.cntThreads
)),
6974 CloseHandle (h_snapshot
);
6980 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6982 /* If we were denied a handle to the process, try again after
6983 enabling the SeDebugPrivilege in our process. */
6986 TOKEN_PRIVILEGES priv_current
;
6988 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6990 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6992 restore_privilege (&priv_current
);
6998 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
7001 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
7002 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7004 buf
= xmalloc (blen
);
7005 result
= get_token_information (token
, TokenUser
,
7006 (LPVOID
)buf
, blen
, &needed
);
7009 memcpy (&user_token
, buf
, sizeof (user_token
));
7010 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
7012 euid
= get_rid (user_token
.User
.Sid
);
7013 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
7018 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
7021 strcpy (uname
, "unknown");
7025 ulength
= strlen (uname
);
7031 /* Determine a reasonable euid and gid values. */
7032 if (xstrcasecmp ("administrator", uname
) == 0)
7034 euid
= 500; /* well-known Administrator uid */
7035 egid
= 513; /* well-known None gid */
7039 /* Get group id and name. */
7040 result
= get_token_information (token
, TokenPrimaryGroup
,
7041 (LPVOID
)buf
, blen
, &needed
);
7042 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7044 buf
= xrealloc (buf
, blen
= needed
);
7045 result
= get_token_information (token
, TokenPrimaryGroup
,
7046 (LPVOID
)buf
, blen
, &needed
);
7050 memcpy (&group_token
, buf
, sizeof (group_token
));
7051 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
7053 egid
= get_rid (group_token
.PrimaryGroup
);
7054 dlength
= sizeof (domain
);
7056 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
7057 gname
, &glength
, NULL
, &dlength
,
7060 w32_add_to_cache (group_token
.PrimaryGroup
,
7064 strcpy (gname
, "None");
7068 glength
= strlen (gname
);
7076 if (!is_windows_9x ())
7078 /* We couldn't open the process token, presumably because of
7079 insufficient access rights. Assume this process is run
7081 strcpy (uname
, "SYSTEM");
7082 strcpy (gname
, "None");
7083 euid
= 18; /* SYSTEM */
7084 egid
= 513; /* None */
7085 glength
= strlen (gname
);
7086 ulength
= strlen (uname
);
7088 /* If we are running under Windows 9X, where security calls are
7089 not supported, we assume all processes are run by the current
7091 else if (GetUserName (uname
, &ulength
))
7093 if (xstrcasecmp ("administrator", uname
) == 0)
7098 strcpy (gname
, "None");
7099 glength
= strlen (gname
);
7100 ulength
= strlen (uname
);
7106 strcpy (uname
, "administrator");
7107 ulength
= strlen (uname
);
7108 strcpy (gname
, "None");
7109 glength
= strlen (gname
);
7112 CloseHandle (token
);
7115 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7116 tem
= make_unibyte_string (uname
, ulength
);
7117 attrs
= Fcons (Fcons (Quser
,
7118 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7120 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7121 tem
= make_unibyte_string (gname
, glength
);
7122 attrs
= Fcons (Fcons (Qgroup
,
7123 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7126 if (global_memory_status_ex (&memstex
))
7127 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7128 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7130 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7131 double, so we need to do this for it... */
7133 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7134 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7135 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7137 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7139 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7140 else if (global_memory_status (&memst
))
7141 totphys
= memst
.dwTotalPhys
/ 1024.0;
7144 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7147 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7149 attrs
= Fcons (Fcons (Qmajflt
,
7150 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7152 attrs
= Fcons (Fcons (Qvsize
,
7153 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7155 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7157 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7160 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7162 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7164 attrs
= Fcons (Fcons (Qmajflt
,
7165 make_fixnum_or_float (mem
.PageFaultCount
)),
7167 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7169 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7172 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7174 DWORD rss
= maxrss
/ 1024;
7176 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7178 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7181 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7183 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7184 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7185 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7186 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7187 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7188 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7191 /* FIXME: Retrieve command line by walking the PEB of the process. */
7194 CloseHandle (h_proc
);
7199 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7200 unsigned long long *totalswap
, unsigned long long *freeswap
)
7203 MEMORY_STATUS_EX memstex
;
7205 /* Use GlobalMemoryStatusEx if available, as it can report more than
7207 if (global_memory_status_ex (&memstex
))
7209 *totalram
= memstex
.ullTotalPhys
;
7210 *freeram
= memstex
.ullAvailPhys
;
7211 *totalswap
= memstex
.ullTotalPageFile
;
7212 *freeswap
= memstex
.ullAvailPageFile
;
7215 else if (global_memory_status (&memst
))
7217 *totalram
= memst
.dwTotalPhys
;
7218 *freeram
= memst
.dwAvailPhys
;
7219 *totalswap
= memst
.dwTotalPageFile
;
7220 *freeswap
= memst
.dwAvailPageFile
;
7228 /* Wrappers for winsock functions to map between our file descriptors
7229 and winsock's handles; also set h_errno for convenience.
7231 To allow Emacs to run on systems which don't have winsock support
7232 installed, we dynamically link to winsock on startup if present, and
7233 otherwise provide the minimum necessary functionality
7234 (eg. gethostname). */
7236 /* function pointers for relevant socket functions */
7237 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7238 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7239 int (PASCAL
*pfn_WSAGetLastError
) (void);
7240 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7241 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7242 WSANETWORKEVENTS
*NetworkEvents
);
7244 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7245 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7246 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7247 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7248 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7249 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7250 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7251 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7252 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7253 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7254 int (PASCAL
*pfn_WSACleanup
) (void);
7256 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7257 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7258 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7259 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7260 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7261 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7262 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7263 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7264 const char * optval
, int optlen
);
7265 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7266 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7268 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7269 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7270 struct sockaddr
* from
, int * fromlen
);
7271 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7272 const struct sockaddr
* to
, int tolen
);
7274 int (PASCAL
*pfn_getaddrinfo
) (const char *, const char *,
7275 const struct addrinfo
*, struct addrinfo
**);
7276 void (PASCAL
*pfn_freeaddrinfo
) (struct addrinfo
*);
7278 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7279 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7280 #ifndef HANDLE_FLAG_INHERIT
7281 #define HANDLE_FLAG_INHERIT 1
7285 static int winsock_inuse
;
7287 BOOL
term_winsock (void);
7292 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7294 release_listen_threads ();
7295 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7296 after WSAStartup returns successfully, but it seems reasonable
7297 to allow unloading winsock anyway in that case. */
7298 if (pfn_WSACleanup () == 0 ||
7299 pfn_WSAGetLastError () == WSAENETDOWN
)
7301 if (FreeLibrary (winsock_lib
))
7310 init_winsock (int load_now
)
7312 WSADATA winsockData
;
7314 if (winsock_lib
!= NULL
)
7317 pfn_SetHandleInformation
7318 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7319 "SetHandleInformation");
7321 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7323 if (winsock_lib
!= NULL
)
7325 /* dynamically link to socket functions */
7327 #define LOAD_PROC(fn) \
7328 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7331 LOAD_PROC (WSAStartup
);
7332 LOAD_PROC (WSASetLastError
);
7333 LOAD_PROC (WSAGetLastError
);
7334 LOAD_PROC (WSAEventSelect
);
7335 LOAD_PROC (WSAEnumNetworkEvents
);
7336 LOAD_PROC (WSACreateEvent
);
7337 LOAD_PROC (WSACloseEvent
);
7340 LOAD_PROC (connect
);
7341 LOAD_PROC (ioctlsocket
);
7344 LOAD_PROC (closesocket
);
7345 LOAD_PROC (shutdown
);
7348 LOAD_PROC (inet_addr
);
7349 LOAD_PROC (gethostname
);
7350 LOAD_PROC (gethostbyname
);
7351 LOAD_PROC (getservbyname
);
7352 LOAD_PROC (getpeername
);
7353 LOAD_PROC (WSACleanup
);
7354 LOAD_PROC (setsockopt
);
7356 LOAD_PROC (getsockname
);
7358 LOAD_PROC (recvfrom
);
7362 /* Try loading functions not available before XP. */
7363 pfn_getaddrinfo
= (void *) GetProcAddress (winsock_lib
, "getaddrinfo");
7364 pfn_freeaddrinfo
= (void *) GetProcAddress (winsock_lib
, "freeaddrinfo");
7365 /* Paranoia: these two functions should go together, so if one
7366 is absent, we cannot use the other. */
7367 if (pfn_getaddrinfo
== NULL
)
7368 pfn_freeaddrinfo
= NULL
;
7369 else if (pfn_freeaddrinfo
== NULL
)
7370 pfn_getaddrinfo
= NULL
;
7372 /* specify version 1.1 of winsock */
7373 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7375 if (winsockData
.wVersion
!= 0x101)
7380 /* Report that winsock exists and is usable, but leave
7381 socket functions disabled. I am assuming that calling
7382 WSAStartup does not require any network interaction,
7383 and in particular does not cause or require a dial-up
7384 connection to be established. */
7387 FreeLibrary (winsock_lib
);
7395 FreeLibrary (winsock_lib
);
7405 /* Function to map winsock error codes to errno codes for those errno
7406 code defined in errno.h (errno values not defined by errno.h are
7407 already in nt/inc/sys/socket.h). */
7414 if (winsock_lib
== NULL
)
7417 wsa_err
= pfn_WSAGetLastError ();
7421 case WSAEACCES
: errno
= EACCES
; break;
7422 case WSAEBADF
: errno
= EBADF
; break;
7423 case WSAEFAULT
: errno
= EFAULT
; break;
7424 case WSAEINTR
: errno
= EINTR
; break;
7425 case WSAEINVAL
: errno
= EINVAL
; break;
7426 case WSAEMFILE
: errno
= EMFILE
; break;
7427 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7428 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7429 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7430 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7431 default: errno
= wsa_err
; break;
7439 if (winsock_lib
!= NULL
)
7440 pfn_WSASetLastError (0);
7443 /* Extend strerror to handle the winsock-specific error codes. */
7447 } _wsa_errlist
[] = {
7448 {WSAEINTR
, "Interrupted function call"},
7449 {WSAEBADF
, "Bad file descriptor"},
7450 {WSAEACCES
, "Permission denied"},
7451 {WSAEFAULT
, "Bad address"},
7452 {WSAEINVAL
, "Invalid argument"},
7453 {WSAEMFILE
, "Too many open files"},
7455 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7456 {WSAEINPROGRESS
, "Operation now in progress"},
7457 {WSAEALREADY
, "Operation already in progress"},
7458 {WSAENOTSOCK
, "Socket operation on non-socket"},
7459 {WSAEDESTADDRREQ
, "Destination address required"},
7460 {WSAEMSGSIZE
, "Message too long"},
7461 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7462 {WSAENOPROTOOPT
, "Bad protocol option"},
7463 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7464 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7465 {WSAEOPNOTSUPP
, "Operation not supported"},
7466 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7467 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7468 {WSAEADDRINUSE
, "Address already in use"},
7469 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7470 {WSAENETDOWN
, "Network is down"},
7471 {WSAENETUNREACH
, "Network is unreachable"},
7472 {WSAENETRESET
, "Network dropped connection on reset"},
7473 {WSAECONNABORTED
, "Software caused connection abort"},
7474 {WSAECONNRESET
, "Connection reset by peer"},
7475 {WSAENOBUFS
, "No buffer space available"},
7476 {WSAEISCONN
, "Socket is already connected"},
7477 {WSAENOTCONN
, "Socket is not connected"},
7478 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7479 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7480 {WSAETIMEDOUT
, "Connection timed out"},
7481 {WSAECONNREFUSED
, "Connection refused"},
7482 {WSAELOOP
, "Network loop"}, /* not sure */
7483 {WSAENAMETOOLONG
, "Name is too long"},
7484 {WSAEHOSTDOWN
, "Host is down"},
7485 {WSAEHOSTUNREACH
, "No route to host"},
7486 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7487 {WSAEPROCLIM
, "Too many processes"},
7488 {WSAEUSERS
, "Too many users"}, /* not sure */
7489 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7490 {WSAESTALE
, "Data is stale"}, /* not sure */
7491 {WSAEREMOTE
, "Remote error"}, /* not sure */
7493 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7494 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7495 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7496 {WSAEDISCON
, "Graceful shutdown in progress"},
7498 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7499 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7500 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7501 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7502 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7503 {WSASYSCALLFAILURE
, "System call failure"},
7504 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7505 {WSATYPE_NOT_FOUND
, "Class type not found"},
7506 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7507 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7508 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7511 {WSAHOST_NOT_FOUND
, "Host not found"},
7512 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7513 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7514 {WSANO_DATA
, "Valid name, no data record of requested type"},
7520 sys_strerror (int error_no
)
7523 static char unknown_msg
[40];
7525 if (error_no
>= 0 && error_no
< sys_nerr
)
7526 return sys_errlist
[error_no
];
7528 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7529 if (_wsa_errlist
[i
].errnum
== error_no
)
7530 return (char *)_wsa_errlist
[i
].msg
;
7532 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7536 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7537 but I believe the method of keeping the socket handle separate (and
7538 insuring it is not inheritable) is the correct one. */
7540 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7542 static int socket_to_fd (SOCKET s
);
7545 sys_socket (int af
, int type
, int protocol
)
7549 if (winsock_lib
== NULL
)
7557 /* call the real socket function */
7558 s
= pfn_socket (af
, type
, protocol
);
7560 if (s
!= INVALID_SOCKET
)
7561 return socket_to_fd (s
);
7567 /* Convert a SOCKET to a file descriptor. */
7569 socket_to_fd (SOCKET s
)
7574 /* Although under NT 3.5 _open_osfhandle will accept a socket
7575 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7576 that does not work under NT 3.1. However, we can get the same
7577 effect by using a backdoor function to replace an existing
7578 descriptor handle with the one we want. */
7580 /* allocate a file descriptor (with appropriate flags) */
7581 fd
= _open ("NUL:", _O_RDWR
);
7584 /* Make a non-inheritable copy of the socket handle. Note
7585 that it is possible that sockets aren't actually kernel
7586 handles, which appears to be the case on Windows 9x when
7587 the MS Proxy winsock client is installed. */
7589 /* Apparently there is a bug in NT 3.51 with some service
7590 packs, which prevents using DuplicateHandle to make a
7591 socket handle non-inheritable (causes WSACleanup to
7592 hang). The work-around is to use SetHandleInformation
7593 instead if it is available and implemented. */
7594 if (pfn_SetHandleInformation
)
7596 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7600 HANDLE parent
= GetCurrentProcess ();
7601 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7603 if (DuplicateHandle (parent
,
7609 DUPLICATE_SAME_ACCESS
))
7611 /* It is possible that DuplicateHandle succeeds even
7612 though the socket wasn't really a kernel handle,
7613 because a real handle has the same value. So
7614 test whether the new handle really is a socket. */
7615 unsigned long nonblocking
= 0;
7616 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7618 pfn_closesocket (s
);
7623 CloseHandle (new_s
);
7628 eassert (fd
< MAXDESC
);
7629 fd_info
[fd
].hnd
= (HANDLE
) s
;
7631 /* set our own internal flags */
7632 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7638 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7640 /* attach child_process to fd_info */
7641 if (fd_info
[ fd
].cp
!= NULL
)
7643 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7647 fd_info
[ fd
].cp
= cp
;
7650 winsock_inuse
++; /* count open sockets */
7658 pfn_closesocket (s
);
7664 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7666 if (winsock_lib
== NULL
)
7669 return SOCKET_ERROR
;
7673 if (fd_info
[s
].flags
& FILE_SOCKET
)
7675 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7676 if (rc
== SOCKET_ERROR
)
7681 return SOCKET_ERROR
;
7685 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7687 if (winsock_lib
== NULL
)
7690 return SOCKET_ERROR
;
7694 if (fd_info
[s
].flags
& FILE_SOCKET
)
7696 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7697 if (rc
== SOCKET_ERROR
)
7700 /* If this is a non-blocking 'connect', set the bit in flags
7701 that will tell reader_thread to wait for connection
7702 before trying to read. */
7703 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7705 errno
= EINPROGRESS
; /* that's what process.c expects */
7706 fd_info
[s
].flags
|= FILE_CONNECT
;
7712 return SOCKET_ERROR
;
7716 sys_htons (u_short hostshort
)
7718 return (winsock_lib
!= NULL
) ?
7719 pfn_htons (hostshort
) : hostshort
;
7723 sys_ntohs (u_short netshort
)
7725 return (winsock_lib
!= NULL
) ?
7726 pfn_ntohs (netshort
) : netshort
;
7730 sys_inet_addr (const char * cp
)
7732 return (winsock_lib
!= NULL
) ?
7733 pfn_inet_addr (cp
) : INADDR_NONE
;
7737 sys_gethostname (char * name
, int namelen
)
7739 if (winsock_lib
!= NULL
)
7744 retval
= pfn_gethostname (name
, namelen
);
7745 if (retval
== SOCKET_ERROR
)
7750 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7751 return !GetComputerName (name
, (DWORD
*)&namelen
);
7754 return SOCKET_ERROR
;
7758 sys_gethostbyname (const char * name
)
7760 struct hostent
* host
;
7761 int h_err
= h_errno
;
7763 if (winsock_lib
== NULL
)
7765 h_errno
= NO_RECOVERY
;
7771 host
= pfn_gethostbyname (name
);
7783 sys_getservbyname (const char * name
, const char * proto
)
7785 struct servent
* serv
;
7787 if (winsock_lib
== NULL
)
7794 serv
= pfn_getservbyname (name
, proto
);
7801 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7803 if (winsock_lib
== NULL
)
7806 return SOCKET_ERROR
;
7810 if (fd_info
[s
].flags
& FILE_SOCKET
)
7812 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7813 if (rc
== SOCKET_ERROR
)
7818 return SOCKET_ERROR
;
7822 sys_getaddrinfo (const char *node
, const char *service
,
7823 const struct addrinfo
*hints
, struct addrinfo
**res
)
7827 if (winsock_lib
== NULL
)
7830 return SOCKET_ERROR
;
7834 if (pfn_getaddrinfo
)
7835 rc
= pfn_getaddrinfo (node
, service
, hints
, res
);
7839 struct hostent
*host_info
;
7840 struct gai_storage
{
7841 struct addrinfo addrinfo
;
7842 struct sockaddr_in sockaddr_in
;
7845 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7846 if (hints
&& hints
->ai_flags
!= 0)
7848 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7850 return WSAHOST_NOT_FOUND
;
7854 const char *protocol
=
7855 (hints
&& hints
->ai_socktype
== SOCK_DGRAM
) ? "udp" : "tcp";
7856 struct servent
*srv
= sys_getservbyname (service
, protocol
);
7860 else if (*service
>= '0' && *service
<= '9')
7864 port
= strtoul (service
, &endp
, 10);
7865 if (*endp
|| port
> 65536)
7866 return WSAHOST_NOT_FOUND
;
7867 port
= sys_htons ((unsigned short) port
);
7870 return WSAHOST_NOT_FOUND
;
7873 gai_storage
= xzalloc (sizeof *gai_storage
);
7874 gai_storage
->sockaddr_in
.sin_port
= port
;
7875 host_info
= sys_gethostbyname (node
);
7878 memcpy (&gai_storage
->sockaddr_in
.sin_addr
,
7879 host_info
->h_addr
, host_info
->h_length
);
7880 gai_storage
->sockaddr_in
.sin_family
= host_info
->h_addrtype
;
7884 /* Attempt to interpret host as numeric inet address. */
7885 unsigned long numeric_addr
= sys_inet_addr (node
);
7887 if (numeric_addr
== -1)
7890 return WSAHOST_NOT_FOUND
;
7893 memcpy (&gai_storage
->sockaddr_in
.sin_addr
, &numeric_addr
,
7894 sizeof (gai_storage
->sockaddr_in
.sin_addr
));
7895 gai_storage
->sockaddr_in
.sin_family
= (hints
) ? hints
->ai_family
: 0;
7898 gai_storage
->addrinfo
.ai_addr
=
7899 (struct sockaddr
*)&gai_storage
->sockaddr_in
;
7900 gai_storage
->addrinfo
.ai_addrlen
= sizeof (gai_storage
->sockaddr_in
);
7901 gai_storage
->addrinfo
.ai_protocol
= (hints
) ? hints
->ai_protocol
: 0;
7902 gai_storage
->addrinfo
.ai_socktype
= (hints
) ? hints
->ai_socktype
: 0;
7903 gai_storage
->addrinfo
.ai_family
= gai_storage
->sockaddr_in
.sin_family
;
7904 gai_storage
->addrinfo
.ai_next
= NULL
;
7906 *res
= &gai_storage
->addrinfo
;
7914 sys_freeaddrinfo (struct addrinfo
*ai
)
7916 if (winsock_lib
== NULL
)
7923 if (pfn_freeaddrinfo
)
7924 pfn_freeaddrinfo (ai
);
7927 eassert (ai
->ai_next
== NULL
);
7933 sys_shutdown (int s
, int how
)
7935 if (winsock_lib
== NULL
)
7938 return SOCKET_ERROR
;
7942 if (fd_info
[s
].flags
& FILE_SOCKET
)
7944 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7945 if (rc
== SOCKET_ERROR
)
7950 return SOCKET_ERROR
;
7954 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7956 if (winsock_lib
== NULL
)
7959 return SOCKET_ERROR
;
7963 if (fd_info
[s
].flags
& FILE_SOCKET
)
7965 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7966 (const char *)optval
, optlen
);
7967 if (rc
== SOCKET_ERROR
)
7972 return SOCKET_ERROR
;
7976 sys_listen (int s
, int backlog
)
7978 if (winsock_lib
== NULL
)
7981 return SOCKET_ERROR
;
7985 if (fd_info
[s
].flags
& FILE_SOCKET
)
7987 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7988 if (rc
== SOCKET_ERROR
)
7991 fd_info
[s
].flags
|= FILE_LISTEN
;
7995 return SOCKET_ERROR
;
7999 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
8001 if (winsock_lib
== NULL
)
8004 return SOCKET_ERROR
;
8008 if (fd_info
[s
].flags
& FILE_SOCKET
)
8010 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
8011 if (rc
== SOCKET_ERROR
)
8016 return SOCKET_ERROR
;
8020 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
8022 if (winsock_lib
== NULL
)
8029 if (fd_info
[s
].flags
& FILE_LISTEN
)
8031 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
8033 if (t
== INVALID_SOCKET
)
8036 fd
= socket_to_fd (t
);
8040 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8041 ResetEvent (fd_info
[s
].cp
->char_avail
);
8050 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
8051 struct sockaddr
* from
, int * fromlen
)
8053 if (winsock_lib
== NULL
)
8056 return SOCKET_ERROR
;
8060 if (fd_info
[s
].flags
& FILE_SOCKET
)
8062 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
8063 if (rc
== SOCKET_ERROR
)
8068 return SOCKET_ERROR
;
8072 sys_sendto (int s
, const char * buf
, int len
, int flags
,
8073 const struct sockaddr
* to
, int tolen
)
8075 if (winsock_lib
== NULL
)
8078 return SOCKET_ERROR
;
8082 if (fd_info
[s
].flags
& FILE_SOCKET
)
8084 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
8085 if (rc
== SOCKET_ERROR
)
8090 return SOCKET_ERROR
;
8093 /* Windows does not have an fcntl function. Provide an implementation
8094 good enough for Emacs. */
8096 fcntl (int s
, int cmd
, int options
)
8098 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8099 invoked in a context where fd1 is closed and all descriptors less
8100 than fd1 are open, so sys_dup is an adequate implementation. */
8101 if (cmd
== F_DUPFD_CLOEXEC
)
8105 if (fd_info
[s
].flags
& FILE_SOCKET
)
8107 if (winsock_lib
== NULL
)
8113 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8115 unsigned long nblock
= 1;
8116 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
8117 if (rc
== SOCKET_ERROR
)
8119 /* Keep track of the fact that we set this to non-blocking. */
8120 fd_info
[s
].flags
|= FILE_NDELAY
;
8126 return SOCKET_ERROR
;
8129 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
8130 == (FILE_PIPE
| FILE_WRITE
))
8132 /* Force our writes to pipes be non-blocking. */
8133 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8135 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
8136 DWORD pipe_mode
= PIPE_NOWAIT
;
8138 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
8140 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8141 return SOCKET_ERROR
;
8143 fd_info
[s
].flags
|= FILE_NDELAY
;
8149 return SOCKET_ERROR
;
8153 return SOCKET_ERROR
;
8157 /* Shadow main io functions: we need to handle pipes and sockets more
8171 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
8173 child_process
* cp
= fd_info
[fd
].cp
;
8175 fd_info
[fd
].cp
= NULL
;
8177 if (CHILD_ACTIVE (cp
))
8179 /* if last descriptor to active child_process then cleanup */
8181 for (i
= 0; i
< MAXDESC
; i
++)
8185 if (fd_info
[i
].cp
== cp
)
8190 if (fd_info
[fd
].flags
& FILE_SOCKET
)
8192 if (winsock_lib
== NULL
) emacs_abort ();
8194 pfn_shutdown (SOCK_HANDLE (fd
), 2);
8195 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
8197 winsock_inuse
--; /* count open sockets */
8199 /* If the process handle is NULL, it's either a socket
8200 or serial connection, or a subprocess that was
8201 already reaped by reap_subprocess, but whose
8202 resources were not yet freed, because its output was
8203 not fully read yet by the time it was reaped. (This
8204 usually happens with async subprocesses whose output
8205 is being read by Emacs.) Otherwise, this process was
8206 not reaped yet, so we set its FD to a negative value
8207 to make sure sys_select will eventually get to
8208 calling the SIGCHLD handler for it, which will then
8209 invoke waitpid and reap_subprocess. */
8210 if (cp
->procinfo
.hProcess
== NULL
)
8218 if (fd
>= 0 && fd
< MAXDESC
)
8219 fd_info
[fd
].flags
= 0;
8221 /* Note that sockets do not need special treatment here (at least on
8222 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8223 closesocket is equivalent to CloseHandle, which is to be expected
8224 because socket handles are fully fledged kernel handles. */
8236 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8238 /* duplicate our internal info as well */
8239 fd_info
[new_fd
] = fd_info
[fd
];
8245 sys_dup2 (int src
, int dst
)
8249 if (dst
< 0 || dst
>= MAXDESC
)
8255 /* MS _dup2 seems to have weird side effect when invoked with 2
8256 identical arguments: an attempt to fclose the corresponding stdio
8257 stream after that hangs (we do close standard streams in
8258 init_ntproc). Attempt to avoid that by not calling _dup2 that
8259 way: if SRC is valid, we know that dup2 should be a no-op, so do
8260 nothing and return DST. */
8263 if ((HANDLE
)_get_osfhandle (src
) == INVALID_HANDLE_VALUE
)
8271 /* Make sure we close the destination first if it's a pipe or socket. */
8272 if (fd_info
[dst
].flags
!= 0)
8275 rc
= _dup2 (src
, dst
);
8278 /* Duplicate our internal info as well. */
8279 fd_info
[dst
] = fd_info
[src
];
8281 return rc
== 0 ? dst
: rc
;
8285 pipe2 (int * phandles
, int pipe2_flags
)
8289 unsigned pipe_size
= 0;
8291 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8293 /* Allow Lisp to override the default buffer size of the pipe. */
8294 if (w32_pipe_buffer_size
> 0 && w32_pipe_buffer_size
< UINT_MAX
)
8295 pipe_size
= w32_pipe_buffer_size
;
8297 /* make pipe handles non-inheritable; when we spawn a child, we
8298 replace the relevant handle with an inheritable one. Also put
8299 pipes into binary mode; we will do text mode translation ourselves
8301 rc
= _pipe (phandles
, pipe_size
, _O_NOINHERIT
| _O_BINARY
);
8305 /* Protect against overflow, since Windows can open more handles than
8306 our fd_info array has room for. */
8307 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8309 _close (phandles
[0]);
8310 _close (phandles
[1]);
8316 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8317 fd_info
[phandles
[0]].flags
= flags
;
8319 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8320 fd_info
[phandles
[1]].flags
= flags
;
8327 /* Function to do blocking read of one byte, needed to implement
8328 select. It is only allowed on communication ports, sockets, or
8331 _sys_read_ahead (int fd
)
8336 if (fd
< 0 || fd
>= MAXDESC
)
8337 return STATUS_READ_ERROR
;
8339 cp
= fd_info
[fd
].cp
;
8341 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8342 return STATUS_READ_ERROR
;
8344 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8345 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8347 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8351 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8352 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8353 cp
->status
= STATUS_READ_IN_PROGRESS
;
8355 if (fd_info
[fd
].flags
& FILE_PIPE
)
8357 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8359 /* Give subprocess time to buffer some more output for us before
8360 reporting that input is available; we need this because Windows 95
8361 connects DOS programs to pipes by making the pipe appear to be
8362 the normal console stdout - as a result most DOS programs will
8363 write to stdout without buffering, ie. one character at a
8364 time. Even some W32 programs do this - "dir" in a command
8365 shell on NT is very slow if we don't do this. */
8368 int wait
= w32_pipe_read_delay
;
8374 /* Yield remainder of our time slice, effectively giving a
8375 temporary priority boost to the child process. */
8379 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8381 HANDLE hnd
= fd_info
[fd
].hnd
;
8382 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8385 /* Configure timeouts for blocking read. */
8386 if (!GetCommTimeouts (hnd
, &ct
))
8388 cp
->status
= STATUS_READ_ERROR
;
8389 return STATUS_READ_ERROR
;
8391 ct
.ReadIntervalTimeout
= 0;
8392 ct
.ReadTotalTimeoutMultiplier
= 0;
8393 ct
.ReadTotalTimeoutConstant
= 0;
8394 if (!SetCommTimeouts (hnd
, &ct
))
8396 cp
->status
= STATUS_READ_ERROR
;
8397 return STATUS_READ_ERROR
;
8400 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8402 if (GetLastError () != ERROR_IO_PENDING
)
8404 cp
->status
= STATUS_READ_ERROR
;
8405 return STATUS_READ_ERROR
;
8407 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8409 cp
->status
= STATUS_READ_ERROR
;
8410 return STATUS_READ_ERROR
;
8414 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8416 unsigned long nblock
= 0;
8417 /* We always want this to block, so temporarily disable NDELAY. */
8418 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8419 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8421 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8423 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8426 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8430 if (rc
== sizeof (char))
8431 cp
->status
= STATUS_READ_SUCCEEDED
;
8433 cp
->status
= STATUS_READ_FAILED
;
8439 _sys_wait_accept (int fd
)
8445 if (fd
< 0 || fd
>= MAXDESC
)
8446 return STATUS_READ_ERROR
;
8448 cp
= fd_info
[fd
].cp
;
8450 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8451 return STATUS_READ_ERROR
;
8453 cp
->status
= STATUS_READ_FAILED
;
8455 hEv
= pfn_WSACreateEvent ();
8456 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8457 if (rc
!= SOCKET_ERROR
)
8460 rc
= WaitForSingleObject (hEv
, 500);
8462 } while (rc
== WAIT_TIMEOUT
8463 && cp
->status
!= STATUS_READ_ERROR
8465 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8466 if (rc
== WAIT_OBJECT_0
)
8467 cp
->status
= STATUS_READ_SUCCEEDED
;
8469 pfn_WSACloseEvent (hEv
);
8475 _sys_wait_connect (int fd
)
8481 if (fd
< 0 || fd
>= MAXDESC
)
8482 return STATUS_READ_ERROR
;
8484 cp
= fd_info
[fd
].cp
;
8485 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8486 return STATUS_READ_ERROR
;
8488 cp
->status
= STATUS_READ_FAILED
;
8490 hEv
= pfn_WSACreateEvent ();
8491 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8492 if (rc
!= SOCKET_ERROR
)
8495 rc
= WaitForSingleObject (hEv
, 500);
8497 } while (rc
== WAIT_TIMEOUT
8498 && cp
->status
!= STATUS_READ_ERROR
8500 if (rc
== WAIT_OBJECT_0
)
8502 /* We've got an event, but it could be a successful
8503 connection, or it could be a failure. Find out
8505 WSANETWORKEVENTS events
;
8507 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8508 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8509 && events
.iErrorCode
[FD_CONNECT_BIT
])
8511 cp
->status
= STATUS_CONNECT_FAILED
;
8512 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8516 cp
->status
= STATUS_READ_SUCCEEDED
;
8520 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8523 pfn_WSACloseEvent (hEv
);
8529 sys_read (int fd
, char * buffer
, unsigned int count
)
8534 char * orig_buffer
= buffer
;
8542 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8544 child_process
*cp
= fd_info
[fd
].cp
;
8546 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8554 /* re-read CR carried over from last read */
8555 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8557 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8561 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8564 /* presence of a child_process structure means we are operating in
8565 non-blocking mode - otherwise we just call _read directly.
8566 Note that the child_process structure might be missing because
8567 reap_subprocess has been called; in this case the pipe is
8568 already broken, so calling _read on it is okay. */
8571 int current_status
= cp
->status
;
8573 switch (current_status
)
8575 case STATUS_READ_FAILED
:
8576 case STATUS_READ_ERROR
:
8577 /* report normal EOF if nothing in buffer */
8579 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8582 case STATUS_READ_READY
:
8583 case STATUS_READ_IN_PROGRESS
:
8585 /* This happens all the time during GnuTLS handshake
8586 with the remote, evidently because GnuTLS waits for
8587 the read to complete by retrying the read operation
8588 upon EAGAIN. So I'm disabling the DebPrint to avoid
8589 wasting cycles on something that is not a real
8590 problem. Enable if you need to debug something that
8592 DebPrint (("sys_read called when read is in progress %d\n",
8595 errno
= EWOULDBLOCK
;
8598 case STATUS_READ_SUCCEEDED
:
8599 /* consume read-ahead char */
8600 *buffer
++ = cp
->chr
;
8603 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8604 ResetEvent (cp
->char_avail
);
8606 case STATUS_READ_ACKNOWLEDGED
:
8607 case STATUS_CONNECT_FAILED
:
8611 DebPrint (("sys_read: bad status %d\n", current_status
));
8616 if (fd_info
[fd
].flags
& FILE_PIPE
)
8618 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8619 to_read
= min (waiting
, (DWORD
) count
);
8622 nchars
+= _read (fd
, buffer
, to_read
);
8624 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8626 HANDLE hnd
= fd_info
[fd
].hnd
;
8627 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8633 /* Configure timeouts for non-blocking read. */
8634 if (!GetCommTimeouts (hnd
, &ct
))
8639 ct
.ReadIntervalTimeout
= MAXDWORD
;
8640 ct
.ReadTotalTimeoutMultiplier
= 0;
8641 ct
.ReadTotalTimeoutConstant
= 0;
8642 if (!SetCommTimeouts (hnd
, &ct
))
8648 if (!ResetEvent (ovl
->hEvent
))
8653 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8655 if (GetLastError () != ERROR_IO_PENDING
)
8660 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8669 else /* FILE_SOCKET */
8671 if (winsock_lib
== NULL
) emacs_abort ();
8673 /* When a non-blocking 'connect' call fails,
8674 wait_reading_process_output detects this by calling
8675 'getpeername', and then attempts to obtain the connection
8676 error code by trying to read 1 byte from the socket. If
8677 we try to serve that read by calling 'recv' below, the
8678 error we get is a generic WSAENOTCONN, not the actual
8679 connection error. So instead, we use the actual error
8680 code stashed by '_sys_wait_connect' in cp->errcode.
8681 Alternatively, we could have used 'getsockopt', like on
8682 GNU/Linux, but: (a) I have no idea whether the winsock
8683 version could hang, as it does "on some systems" (see the
8684 comment in process.c); and (b) 'getsockopt' on Windows is
8685 documented to clear the socket error for the entire
8686 process, which I'm not sure is TRT; FIXME. */
8687 if (current_status
== STATUS_CONNECT_FAILED
8688 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8689 && cp
->errcode
!= 0)
8691 pfn_WSASetLastError (cp
->errcode
);
8695 /* Do the equivalent of a non-blocking read. */
8696 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8697 if (waiting
== 0 && nchars
== 0)
8699 errno
= EWOULDBLOCK
;
8705 /* always use binary mode for sockets */
8706 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8707 if (res
== SOCKET_ERROR
)
8710 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8711 errno
, SOCK_HANDLE (fd
)));
8720 int nread
= _read (fd
, buffer
, count
);
8723 else if (nchars
== 0)
8728 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8729 /* Perform text mode translation if required. */
8730 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8732 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8733 /* If buffer contains only CR, return that. To be absolutely
8734 sure we should attempt to read the next char, but in
8735 practice a CR to be followed by LF would not appear by
8736 itself in the buffer. */
8737 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8739 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8745 nchars
= _read (fd
, buffer
, count
);
8750 /* From w32xfns.c */
8751 extern HANDLE interrupt_handle
;
8754 sys_write (int fd
, const void * buffer
, unsigned int count
)
8765 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8767 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8773 /* Perform text mode translation if required. */
8774 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8777 const unsigned char * src
= buffer
;
8778 unsigned char * dst
;
8781 SAFE_NALLOCA (tmpbuf
, 2, count
);
8782 dst
= (unsigned char *)tmpbuf
;
8786 unsigned char *next
;
8787 /* Copy next line or remaining bytes. */
8788 next
= _memccpy (dst
, src
, '\n', nbytes
);
8791 /* Copied one line ending with '\n'. */
8792 int copied
= next
- dst
;
8795 /* Insert '\r' before '\n'. */
8802 /* Copied remaining partial line -> now finished. */
8809 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8811 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8812 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8813 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8816 /* This is async (a.k.a. "overlapped") I/O, so the return value
8817 of FALSE from WriteFile means either an error or the output
8818 will be completed asynchronously (ERROR_IO_PENDING). */
8819 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8821 if (GetLastError () != ERROR_IO_PENDING
)
8828 /* Wait for the write to complete, and watch C-g while
8830 if (detect_input_pending ())
8831 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8832 INFINITE
, QS_ALLINPUT
);
8834 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8838 /* User pressed C-g, cancel write, then leave.
8839 Don't bother cleaning up as we may only get stuck
8840 in buggy drivers. */
8841 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8843 errno
= EIO
; /* Why not EINTR? */
8846 case WAIT_OBJECT_0
+ 1:
8847 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8857 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8859 unsigned long nblock
= 0;
8860 if (winsock_lib
== NULL
) emacs_abort ();
8862 child_process
*cp
= fd_info
[fd
].cp
;
8864 /* If this is a non-blocking socket whose connection is in
8865 progress or terminated with an error already, return the
8866 proper error code to the caller. */
8867 if (cp
!= NULL
&& (fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8869 /* In case connection is in progress, ENOTCONN that would
8870 result from calling pfn_send is not what callers expect. */
8871 if (cp
->status
!= STATUS_CONNECT_FAILED
)
8873 errno
= EWOULDBLOCK
;
8876 /* In case connection failed, use the actual error code
8877 stashed by '_sys_wait_connect' in cp->errcode. */
8878 else if (cp
->errcode
!= 0)
8880 pfn_WSASetLastError (cp
->errcode
);
8886 /* TODO: implement select() properly so non-blocking I/O works. */
8887 /* For now, make sure the write blocks. */
8888 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8889 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8891 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8893 if (nchars
== SOCKET_ERROR
)
8896 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8897 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8900 /* Set the socket back to non-blocking if it was before,
8901 for other operations that support it. */
8902 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8905 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8910 /* Some networked filesystems don't like too large writes, so
8911 break them into smaller chunks. See the Comments section of
8912 the MSDN documentation of WriteFile for details behind the
8913 choice of the value of CHUNK below. See also the thread
8914 http://thread.gmane.org/gmane.comp.version-control.git/145294
8915 in the git mailing list. */
8916 const unsigned char *p
= buffer
;
8917 const bool is_pipe
= (fd
< MAXDESC
8918 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8919 == (FILE_PIPE
| FILE_NDELAY
)));
8920 /* Some programs, notably Node.js's node.exe, seem to never
8921 completely empty the pipe, so writing more than the size of
8922 the pipe's buffer always returns ENOSPC, and we loop forever
8923 between send_process and here. As a workaround, write no
8924 more than the pipe's buffer can hold. */
8925 DWORD pipe_buffer_size
;
8928 if (!GetNamedPipeInfo ((HANDLE
)_get_osfhandle (fd
),
8929 NULL
, &pipe_buffer_size
, NULL
, NULL
))
8931 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
8932 pipe_buffer_size
= 4096;
8935 const unsigned chunk
= is_pipe
? pipe_buffer_size
: 30 * 1024 * 1024;
8941 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8942 int n
= _write (fd
, p
, this_chunk
);
8948 /* When there's no buffer space in a pipe that is in the
8949 non-blocking mode, _write returns ENOSPC. We return
8950 EAGAIN instead, which should trigger the logic in
8951 send_process that enters waiting loop and calls
8952 wait_reading_process_output to allow process input to
8953 be accepted during the wait. Those calls to
8954 wait_reading_process_output allow sys_select to
8955 notice when process input becomes available, thus
8956 avoiding deadlock whereby each side of the pipe is
8957 blocked on write, waiting for the other party to read
8958 its end of the pipe. */
8959 if (errno
== ENOSPC
&& is_pipe
)
8965 else if (n
< this_chunk
)
8977 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8979 /* Return information about network interface IFNAME, or about all
8980 interfaces (if IFNAME is nil). */
8982 network_interface_get_info (Lisp_Object ifname
)
8984 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8985 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8986 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8987 Lisp_Object res
= Qnil
;
8989 if (retval
== ERROR_BUFFER_OVERFLOW
)
8991 ainfo
= xrealloc (ainfo
, ainfo_len
);
8992 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8995 if (retval
== ERROR_SUCCESS
)
8997 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8998 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
9000 struct sockaddr_in sa
;
9002 /* For the below, we need some winsock functions, so make sure
9003 the winsock DLL is loaded. If we cannot successfully load
9004 it, they will have no use of the information we provide,
9006 if (!winsock_lib
&& !init_winsock (1))
9009 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
9011 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
9013 /* Present Unix-compatible interface names, instead of the
9014 Windows names, which are really GUIDs not readable by
9016 static const char *ifmt
[] = {
9017 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9032 switch (adapter
->Type
)
9034 case MIB_IF_TYPE_ETHERNET
:
9035 /* Windows before Vista reports wireless adapters as
9036 Ethernet. Work around by looking at the Description
9038 if (strstr (adapter
->Description
, "Wireless "))
9041 if_num
= wlan_count
++;
9045 ifmt_idx
= ETHERNET
;
9046 if_num
= eth_count
++;
9049 case MIB_IF_TYPE_TOKENRING
:
9050 ifmt_idx
= TOKENRING
;
9051 if_num
= tr_count
++;
9053 case MIB_IF_TYPE_FDDI
:
9055 if_num
= fddi_count
++;
9057 case MIB_IF_TYPE_PPP
:
9059 if_num
= ppp_count
++;
9061 case MIB_IF_TYPE_SLIP
:
9063 if_num
= sl_count
++;
9065 case IF_TYPE_IEEE80211
:
9067 if_num
= wlan_count
++;
9069 case MIB_IF_TYPE_LOOPBACK
:
9072 ifmt_idx
= LOOPBACK
;
9073 if_num
= lo_count
++;
9079 ifmt_idx
= OTHER_IF
;
9080 if_num
= ifx_count
++;
9083 if (ifmt_idx
== NONE
)
9085 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
9087 sa
.sin_family
= AF_INET
;
9088 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
9089 if (ip_addr
== INADDR_NONE
)
9091 /* Bogus address, skip this interface. */
9094 sa
.sin_addr
.s_addr
= ip_addr
;
9097 res
= Fcons (Fcons (build_string (namebuf
),
9098 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9099 sizeof (struct sockaddr
))),
9101 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
9103 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
9104 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
9105 Lisp_Object flags
= Qnil
;
9109 /* Flags. We guess most of them by type, since the
9110 Windows flags are different and hard to get by. */
9111 flags
= Fcons (intern ("up"), flags
);
9112 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
9114 flags
= Fcons (intern ("broadcast"), flags
);
9115 flags
= Fcons (intern ("multicast"), flags
);
9117 flags
= Fcons (intern ("running"), flags
);
9118 if (ifmt_idx
== PPP
)
9120 flags
= Fcons (intern ("pointopoint"), flags
);
9121 flags
= Fcons (intern ("noarp"), flags
);
9123 if (adapter
->HaveWins
)
9124 flags
= Fcons (intern ("WINS"), flags
);
9125 if (adapter
->DhcpEnabled
)
9126 flags
= Fcons (intern ("dynamic"), flags
);
9128 res
= Fcons (flags
, res
);
9130 /* Hardware address and its family. */
9131 for (n
= 0; n
< adapter
->AddressLength
; n
++)
9132 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
9133 /* Windows does not support AF_LINK or AF_PACKET family
9134 of addresses. Use an arbitrary family number that is
9135 identical to what GNU/Linux returns. */
9136 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
9139 sa
.sin_family
= AF_INET
;
9140 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
9141 if (net_mask
!= INADDR_NONE
)
9143 sa
.sin_addr
.s_addr
= net_mask
;
9145 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9146 sizeof (struct sockaddr
)),
9150 res
= Fcons (Qnil
, res
);
9152 sa
.sin_family
= AF_INET
;
9153 if (ip_addr
!= INADDR_NONE
)
9155 /* Broadcast address is only reported by
9156 GetAdaptersAddresses, which is of limited
9157 availability. Generate it on our own. */
9158 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
9160 sa
.sin_addr
.s_addr
= bcast_addr
;
9162 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9163 sizeof (struct sockaddr
)),
9167 sa
.sin_addr
.s_addr
= ip_addr
;
9169 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9170 sizeof (struct sockaddr
)),
9174 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
9177 /* GetAdaptersInfo is documented to not report loopback
9178 interfaces, so we generate one out of thin air. */
9181 sa
.sin_family
= AF_INET
;
9185 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9186 res
= Fcons (Fcons (build_string ("lo"),
9187 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9188 sizeof (struct sockaddr
))),
9191 else if (strcmp (SSDATA (ifname
), "lo") == 0)
9193 res
= Fcons (Fcons (intern ("running"),
9194 Fcons (intern ("loopback"),
9195 Fcons (intern ("up"), Qnil
))), Qnil
);
9196 /* 772 is what 3 different GNU/Linux systems report for
9197 the loopback interface. */
9198 res
= Fcons (Fcons (make_number (772),
9199 Fmake_vector (make_number (6),
9202 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
9203 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9204 sizeof (struct sockaddr
)),
9206 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
9207 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9208 sizeof (struct sockaddr
)),
9210 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9211 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9212 sizeof (struct sockaddr
)),
9225 network_interface_list (void)
9227 return network_interface_get_info (Qnil
);
9231 network_interface_info (Lisp_Object ifname
)
9233 CHECK_STRING (ifname
);
9234 return network_interface_get_info (ifname
);
9238 /* The Windows CRT functions are "optimized for speed", so they don't
9239 check for timezone and DST changes if they were last called less
9240 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9241 all Emacs features that repeatedly call time functions (e.g.,
9242 display-time) are in real danger of missing timezone and DST
9243 changes. Calling tzset before each localtime call fixes that. */
9245 sys_localtime (const time_t *t
)
9248 return localtime (t
);
9253 /* Try loading LIBRARY_ID from the file(s) specified in
9254 Vdynamic_library_alist. If the library is loaded successfully,
9255 return the handle of the DLL, and record the filename in the
9256 property :loaded-from of LIBRARY_ID. If the library could not be
9257 found, or when it was already loaded (because the handle is not
9258 recorded anywhere, and so is lost after use), return NULL.
9260 We could also save the handle in :loaded-from, but currently
9261 there's no use case for it. */
9263 w32_delayed_load (Lisp_Object library_id
)
9265 HMODULE dll_handle
= NULL
;
9267 CHECK_SYMBOL (library_id
);
9269 if (CONSP (Vdynamic_library_alist
)
9270 && NILP (Fassq (library_id
, Vlibrary_cache
)))
9272 Lisp_Object found
= Qnil
;
9273 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
9276 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
9278 Lisp_Object dll
= XCAR (dlls
);
9279 char name
[MAX_UTF8_PATH
];
9283 dll
= ENCODE_FILE (dll
);
9284 if (w32_unicode_filenames
)
9286 wchar_t name_w
[MAX_PATH
];
9288 filename_to_utf16 (SSDATA (dll
), name_w
);
9289 dll_handle
= LoadLibraryW (name_w
);
9292 res
= GetModuleFileNameW (dll_handle
, name_w
,
9295 filename_from_utf16 (name_w
, name
);
9300 char name_a
[MAX_PATH
];
9302 filename_to_ansi (SSDATA (dll
), name_a
);
9303 dll_handle
= LoadLibraryA (name_a
);
9306 res
= GetModuleFileNameA (dll_handle
, name_a
,
9309 filename_from_ansi (name_a
, name
);
9314 ptrdiff_t len
= strlen (name
);
9317 /* Possibly truncated */
9318 ? make_specified_string (name
, -1, len
, 1)
9320 /* This prevents thread start and end notifications
9321 from being sent to the DLL, for every thread we
9322 start. We don't need those notifications because
9323 threads we create never use any of these DLLs, only
9324 the main thread uses them. This is supposed to
9325 speed up thread creation. */
9326 DisableThreadLibraryCalls (dll_handle
);
9331 Fput (library_id
, QCloaded_from
, found
);
9339 check_windows_init_file (void)
9341 /* A common indication that Emacs is not installed properly is when
9342 it cannot find the Windows installation file. If this file does
9343 not exist in the expected place, tell the user. */
9345 if (!noninteractive
&& !inhibit_window_system
9346 /* Vload_path is not yet initialized when we are loading
9348 && NILP (Vpurify_flag
))
9350 Lisp_Object init_file
;
9353 /* Implementation note: this function runs early during Emacs
9354 startup, before startup.el is run. So Vload_path is still in
9355 its initial unibyte form, but it holds UTF-8 encoded file
9356 names, since init_callproc was already called. So we do not
9357 need to ENCODE_FILE here, but we do need to convert the file
9358 names from UTF-8 to ANSI. */
9359 init_file
= build_string ("term/w32-win");
9360 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9363 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9364 char *init_file_name
= SSDATA (init_file
);
9365 char *load_path
= SSDATA (load_path_print
);
9366 char *buffer
= alloca (1024
9367 + strlen (init_file_name
)
9368 + strlen (load_path
));
9373 "The Emacs Windows initialization file \"%s.el\" "
9374 "could not be found in your Emacs installation. "
9375 "Emacs checked the following directories for this file:\n"
9377 "When Emacs cannot find this file, it usually means that it "
9378 "was not installed properly, or its distribution file was "
9379 "not unpacked properly.\nSee the README.W32 file in the "
9380 "top-level Emacs directory for more information.",
9381 init_file_name
, load_path
);
9382 needed
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
,
9383 buffer
, -1, NULL
, 0);
9386 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9388 pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, buffer
,
9390 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9391 NULL
, 0, NULL
, NULL
);
9394 char *msg_a
= alloca (needed
+ 1);
9396 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9403 "Emacs Abort Dialog",
9404 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9405 /* Use the low-level system abort. */
9416 term_ntproc (int ignored
)
9422 /* shutdown the socket interface if necessary */
9429 init_ntproc (int dumping
)
9431 sigset_t initial_mask
= 0;
9433 /* Initialize the socket interface now if available and requested by
9434 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9435 delayed until open-network-stream is called (w32-has-winsock can
9436 also be used to dynamically load or reload winsock).
9438 Conveniently, init_environment is called before us, so
9439 PRELOAD_WINSOCK can be set in the registry. */
9441 /* Always initialize this correctly. */
9444 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9445 init_winsock (TRUE
);
9447 /* Initial preparation for subprocess support: replace our standard
9448 handles with non-inheritable versions. */
9451 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9452 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9453 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9455 parent
= GetCurrentProcess ();
9457 /* ignore errors when duplicating and closing; typically the
9458 handles will be invalid when running as a gui program. */
9459 DuplicateHandle (parent
,
9460 GetStdHandle (STD_INPUT_HANDLE
),
9465 DUPLICATE_SAME_ACCESS
);
9467 DuplicateHandle (parent
,
9468 GetStdHandle (STD_OUTPUT_HANDLE
),
9473 DUPLICATE_SAME_ACCESS
);
9475 DuplicateHandle (parent
,
9476 GetStdHandle (STD_ERROR_HANDLE
),
9481 DUPLICATE_SAME_ACCESS
);
9487 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9488 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9490 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9493 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9494 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9496 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9499 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9500 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9502 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9506 /* unfortunately, atexit depends on implementation of malloc */
9507 /* atexit (term_ntproc); */
9510 /* Make sure we start with all signals unblocked. */
9511 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9512 signal (SIGABRT
, term_ntproc
);
9516 /* determine which drives are fixed, for GetCachedVolumeInformation */
9518 /* GetDriveType must have trailing backslash. */
9519 char drive
[] = "A:\\";
9521 /* Loop over all possible drive letters */
9522 while (*drive
<= 'Z')
9524 /* Record if this drive letter refers to a fixed drive. */
9525 fixed_drives
[DRIVE_INDEX (*drive
)] =
9526 (GetDriveType (drive
) == DRIVE_FIXED
);
9531 /* Reset the volume info cache. */
9532 volume_cache
= NULL
;
9537 shutdown_handler ensures that buffers' autosave files are
9538 up to date when the user logs off, or the system shuts down.
9541 shutdown_handler (DWORD type
)
9543 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9544 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9545 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9546 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9548 /* Shut down cleanly, making sure autosave files are up to date. */
9549 shut_down_emacs (0, Qnil
);
9552 /* Allow other handlers to handle this signal. */
9556 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9557 NT, return a handle to GDI32.DLL. */
9559 maybe_load_unicows_dll (void)
9561 if (os_subtype
== OS_9X
)
9563 HANDLE ret
= LoadLibrary ("Unicows.dll");
9566 /* These two functions are present on Windows 9X as stubs
9567 that always fail. We need the real implementations from
9568 UNICOWS.DLL, so we must call these functions through
9569 pointers, and assign the correct addresses to these
9570 pointers at program startup (see emacs.c, which calls
9571 this function early on). */
9572 pMultiByteToWideChar
=
9573 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9574 pWideCharToMultiByte
=
9575 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9576 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9583 button
= MessageBox (NULL
,
9584 "Emacs cannot load the UNICOWS.DLL library.\n"
9585 "This library is essential for using Emacs\n"
9586 "on this system. You need to install it.\n\n"
9587 "Emacs will exit when you click OK.",
9588 "Emacs cannot load UNICOWS.DLL",
9589 MB_ICONERROR
| MB_TASKMODAL
9590 | MB_SETFOREGROUND
| MB_OK
);
9601 /* On NT family of Windows, these two functions are always
9602 linked in, so we just assign their addresses to the 2
9603 pointers; no need for the LoadLibrary dance. */
9604 pMultiByteToWideChar
= MultiByteToWideChar
;
9605 pWideCharToMultiByte
= WideCharToMultiByte
;
9606 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9607 if (w32_major_version
< 5)
9608 multiByteToWideCharFlags
= 0;
9610 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9611 return LoadLibrary ("Gdi32.dll");
9616 globals_of_w32 is used to initialize those global variables that
9617 must always be initialized on startup even when the global variable
9618 initialized is non zero (see the function main in emacs.c).
9621 globals_of_w32 (void)
9623 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9625 get_process_times_fn
= (GetProcessTimes_Proc
)
9626 GetProcAddress (kernel32
, "GetProcessTimes");
9628 DEFSYM (QCloaded_from
, ":loaded-from");
9630 g_b_init_is_windows_9x
= 0;
9631 g_b_init_open_process_token
= 0;
9632 g_b_init_get_token_information
= 0;
9633 g_b_init_lookup_account_sid
= 0;
9634 g_b_init_get_sid_sub_authority
= 0;
9635 g_b_init_get_sid_sub_authority_count
= 0;
9636 g_b_init_get_security_info
= 0;
9637 g_b_init_get_file_security_w
= 0;
9638 g_b_init_get_file_security_a
= 0;
9639 g_b_init_get_security_descriptor_owner
= 0;
9640 g_b_init_get_security_descriptor_group
= 0;
9641 g_b_init_is_valid_sid
= 0;
9642 g_b_init_create_toolhelp32_snapshot
= 0;
9643 g_b_init_process32_first
= 0;
9644 g_b_init_process32_next
= 0;
9645 g_b_init_open_thread_token
= 0;
9646 g_b_init_impersonate_self
= 0;
9647 g_b_init_revert_to_self
= 0;
9648 g_b_init_get_process_memory_info
= 0;
9649 g_b_init_get_process_working_set_size
= 0;
9650 g_b_init_global_memory_status
= 0;
9651 g_b_init_global_memory_status_ex
= 0;
9652 g_b_init_equal_sid
= 0;
9653 g_b_init_copy_sid
= 0;
9654 g_b_init_get_length_sid
= 0;
9655 g_b_init_get_native_system_info
= 0;
9656 g_b_init_get_system_times
= 0;
9657 g_b_init_create_symbolic_link_w
= 0;
9658 g_b_init_create_symbolic_link_a
= 0;
9659 g_b_init_get_security_descriptor_dacl
= 0;
9660 g_b_init_convert_sd_to_sddl
= 0;
9661 g_b_init_convert_sddl_to_sd
= 0;
9662 g_b_init_is_valid_security_descriptor
= 0;
9663 g_b_init_set_file_security_w
= 0;
9664 g_b_init_set_file_security_a
= 0;
9665 g_b_init_set_named_security_info_w
= 0;
9666 g_b_init_set_named_security_info_a
= 0;
9667 g_b_init_get_adapters_info
= 0;
9668 g_b_init_compare_string_w
= 0;
9669 g_b_init_debug_break_process
= 0;
9670 num_of_processors
= 0;
9671 /* The following sets a handler for shutdown notifications for
9672 console apps. This actually applies to Emacs in both console and
9673 GUI modes, since we had to fool windows into thinking emacs is a
9674 console application to get console mode to work. */
9675 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9677 /* "None" is the default group name on standalone workstations. */
9678 strcpy (dflt_group_name
, "None");
9680 /* Reset, in case it has some value inherited from dump time. */
9681 w32_stat_get_owner_group
= 0;
9683 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9684 (a.k.a. "wide") APIs to invoke functions that accept file
9686 if (is_windows_9x ())
9687 w32_unicode_filenames
= 0;
9689 w32_unicode_filenames
= 1;
9692 dynlib_reset_last_error ();
9695 w32_crypto_hprov
= (HCRYPTPROV
)0;
9698 /* For make-serial-process */
9700 serial_open (Lisp_Object port_obj
)
9702 char *port
= SSDATA (port_obj
);
9707 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9708 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9709 if (hnd
== INVALID_HANDLE_VALUE
)
9710 error ("Could not open %s", port
);
9711 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9713 error ("Could not open %s", port
);
9717 error ("Could not create child process");
9719 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9720 fd_info
[ fd
].hnd
= hnd
;
9721 fd_info
[ fd
].flags
|=
9722 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9723 if (fd_info
[ fd
].cp
!= NULL
)
9725 error ("fd_info[fd = %d] is already in use", fd
);
9727 fd_info
[ fd
].cp
= cp
;
9728 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9729 if (cp
->ovl_read
.hEvent
== NULL
)
9730 error ("Could not create read event");
9731 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9732 if (cp
->ovl_write
.hEvent
== NULL
)
9733 error ("Could not create write event");
9738 /* For serial-process-configure */
9740 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9742 Lisp_Object childp2
= Qnil
;
9743 Lisp_Object tem
= Qnil
;
9747 char summary
[4] = "???"; /* This usually becomes "8N1". */
9749 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9750 error ("Not a serial process");
9751 hnd
= fd_info
[ p
->outfd
].hnd
;
9753 childp2
= Fcopy_sequence (p
->childp
);
9755 /* Initialize timeouts for blocking read and blocking write. */
9756 if (!GetCommTimeouts (hnd
, &ct
))
9757 error ("GetCommTimeouts() failed");
9758 ct
.ReadIntervalTimeout
= 0;
9759 ct
.ReadTotalTimeoutMultiplier
= 0;
9760 ct
.ReadTotalTimeoutConstant
= 0;
9761 ct
.WriteTotalTimeoutMultiplier
= 0;
9762 ct
.WriteTotalTimeoutConstant
= 0;
9763 if (!SetCommTimeouts (hnd
, &ct
))
9764 error ("SetCommTimeouts() failed");
9765 /* Read port attributes and prepare default configuration. */
9766 memset (&dcb
, 0, sizeof (dcb
));
9767 dcb
.DCBlength
= sizeof (DCB
);
9768 if (!GetCommState (hnd
, &dcb
))
9769 error ("GetCommState() failed");
9772 dcb
.fAbortOnError
= FALSE
;
9773 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9778 /* Configure speed. */
9779 if (!NILP (Fplist_member (contact
, QCspeed
)))
9780 tem
= Fplist_get (contact
, QCspeed
);
9782 tem
= Fplist_get (p
->childp
, QCspeed
);
9784 dcb
.BaudRate
= XINT (tem
);
9785 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9787 /* Configure bytesize. */
9788 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9789 tem
= Fplist_get (contact
, QCbytesize
);
9791 tem
= Fplist_get (p
->childp
, QCbytesize
);
9793 tem
= make_number (8);
9795 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9796 error (":bytesize must be nil (8), 7, or 8");
9797 dcb
.ByteSize
= XINT (tem
);
9798 summary
[0] = XINT (tem
) + '0';
9799 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9801 /* Configure parity. */
9802 if (!NILP (Fplist_member (contact
, QCparity
)))
9803 tem
= Fplist_get (contact
, QCparity
);
9805 tem
= Fplist_get (p
->childp
, QCparity
);
9806 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9807 error (":parity must be nil (no parity), `even', or `odd'");
9808 dcb
.fParity
= FALSE
;
9809 dcb
.Parity
= NOPARITY
;
9810 dcb
.fErrorChar
= FALSE
;
9815 else if (EQ (tem
, Qeven
))
9819 dcb
.Parity
= EVENPARITY
;
9820 dcb
.fErrorChar
= TRUE
;
9822 else if (EQ (tem
, Qodd
))
9826 dcb
.Parity
= ODDPARITY
;
9827 dcb
.fErrorChar
= TRUE
;
9829 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9831 /* Configure stopbits. */
9832 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9833 tem
= Fplist_get (contact
, QCstopbits
);
9835 tem
= Fplist_get (p
->childp
, QCstopbits
);
9837 tem
= make_number (1);
9839 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9840 error (":stopbits must be nil (1 stopbit), 1, or 2");
9841 summary
[2] = XINT (tem
) + '0';
9842 if (XINT (tem
) == 1)
9843 dcb
.StopBits
= ONESTOPBIT
;
9844 else if (XINT (tem
) == 2)
9845 dcb
.StopBits
= TWOSTOPBITS
;
9846 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9848 /* Configure flowcontrol. */
9849 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9850 tem
= Fplist_get (contact
, QCflowcontrol
);
9852 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9853 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9854 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9855 dcb
.fOutxCtsFlow
= FALSE
;
9856 dcb
.fOutxDsrFlow
= FALSE
;
9857 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9858 dcb
.fDsrSensitivity
= FALSE
;
9859 dcb
.fTXContinueOnXoff
= FALSE
;
9862 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9863 dcb
.XonChar
= 17; /* Control-Q */
9864 dcb
.XoffChar
= 19; /* Control-S */
9867 /* Already configured. */
9869 else if (EQ (tem
, Qhw
))
9871 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9872 dcb
.fOutxCtsFlow
= TRUE
;
9874 else if (EQ (tem
, Qsw
))
9879 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9881 /* Activate configuration. */
9882 if (!SetCommState (hnd
, &dcb
))
9883 error ("SetCommState() failed");
9885 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9886 pset_childp (p
, childp2
);
9889 /* For make-pipe-process */
9891 register_aux_fd (int infd
)
9897 error ("Could not create child process");
9899 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9901 if (fd_info
[ infd
].cp
!= NULL
)
9903 error ("fd_info[fd = %d] is already in use", infd
);
9905 fd_info
[ infd
].cp
= cp
;
9906 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
9912 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9915 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9916 int fd
= process
->infd
;
9918 n
= sys_read (fd
, (char*)buf
, sz
);
9925 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9926 if (err
== EWOULDBLOCK
)
9929 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9935 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9937 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9938 int fd
= process
->outfd
;
9939 ssize_t n
= sys_write (fd
, buf
, sz
);
9941 /* 0 or more bytes written means everything went fine. */
9945 /* Negative bytes written means we got an error in errno.
9946 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9947 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9948 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9952 #endif /* HAVE_GNUTLS */