1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
2 Copyright (C) 1994-1995, 2000-2013 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
23 #include <mingw_time.h>
24 #include <stddef.h> /* for offsetof */
27 #include <float.h> /* for DBL_EPSILON */
34 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
36 #include <sys/utime.h>
39 /* must include CRT headers *before* config.h */
42 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
69 #include "epaths.h" /* for SHELL */
74 /* MinGW64 (_W64) defines these in its _mingw.h. */
75 #if defined(__GNUC__) && !defined(_W64)
76 #define _ANONYMOUS_UNION
77 #define _ANONYMOUS_STRUCT
80 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
81 use a different name to avoid compilation problems. */
82 typedef struct _MEMORY_STATUS_EX
{
85 DWORDLONG ullTotalPhys
;
86 DWORDLONG ullAvailPhys
;
87 DWORDLONG ullTotalPageFile
;
88 DWORDLONG ullAvailPageFile
;
89 DWORDLONG ullTotalVirtual
;
90 DWORDLONG ullAvailVirtual
;
91 DWORDLONG ullAvailExtendedVirtual
;
92 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
94 /* These are here so that GDB would know about these data types. This
95 allows to attach GDB to Emacs when a fatal exception is triggered
96 and Windows pops up the "application needs to be closed" dialog.
97 At that point, _gnu_exception_handler, the top-level exception
98 handler installed by the MinGW startup code, is somewhere on the
99 call-stack of the main thread, so going to that call frame and
100 looking at the argument to _gnu_exception_handler, which is a
101 PEXCEPTION_POINTERS pointer, can reveal the exception code
102 (excptr->ExceptionRecord->ExceptionCode) and the address where the
103 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
104 well as some additional information specific to the exception. */
105 PEXCEPTION_POINTERS excptr
;
106 PEXCEPTION_RECORD excprec
;
112 #include <tlhelp32.h>
117 #if _WIN32_WINNT < 0x0500
118 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
119 /* This either is not in psapi.h or guarded by higher value of
120 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
121 defines it in psapi.h */
122 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
124 DWORD PageFaultCount
;
125 SIZE_T PeakWorkingSetSize
;
126 SIZE_T WorkingSetSize
;
127 SIZE_T QuotaPeakPagedPoolUsage
;
128 SIZE_T QuotaPagedPoolUsage
;
129 SIZE_T QuotaPeakNonPagedPoolUsage
;
130 SIZE_T QuotaNonPagedPoolUsage
;
131 SIZE_T PagefileUsage
;
132 SIZE_T PeakPagefileUsage
;
134 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
138 #include <winioctl.h>
145 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
146 define them by hand if not already defined. */
147 #ifndef SDDL_REVISION_1
148 #define SDDL_REVISION_1 1
149 #endif /* SDDL_REVISION_1 */
151 #if defined(_MSC_VER) || defined(_W64)
152 /* MSVC and MinGW64 don't provide the definition of
153 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
154 which cannot be included because it triggers conflicts with other
155 Windows API headers. So we define it here by hand. */
157 typedef struct _REPARSE_DATA_BUFFER
{
159 USHORT ReparseDataLength
;
163 USHORT SubstituteNameOffset
;
164 USHORT SubstituteNameLength
;
165 USHORT PrintNameOffset
;
166 USHORT PrintNameLength
;
169 } SymbolicLinkReparseBuffer
;
171 USHORT SubstituteNameOffset
;
172 USHORT SubstituteNameLength
;
173 USHORT PrintNameOffset
;
174 USHORT PrintNameLength
;
176 } MountPointReparseBuffer
;
179 } GenericReparseBuffer
;
181 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
183 #ifndef FILE_DEVICE_FILE_SYSTEM
184 #define FILE_DEVICE_FILE_SYSTEM 9
186 #ifndef METHOD_BUFFERED
187 #define METHOD_BUFFERED 0
189 #ifndef FILE_ANY_ACCESS
190 #define FILE_ANY_ACCESS 0x00000000
193 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
195 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
196 #ifndef FSCTL_GET_REPARSE_POINT
197 #define FSCTL_GET_REPARSE_POINT \
198 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
202 /* TCP connection support. */
203 #include <sys/socket.h>
222 #include <iphlpapi.h> /* should be after winsock2.h */
226 #include "w32common.h"
228 #include "w32select.h"
230 #include "dispextern.h" /* for xstrcasecmp */
231 #include "coding.h" /* for Vlocale_coding_system */
233 #include "careadlinkat.h"
234 #include "allocator.h"
236 /* For serial_configure and serial_open. */
239 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
240 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
242 Lisp_Object QCloaded_from
;
244 void globals_of_w32 (void);
245 static DWORD
get_rid (PSID
);
246 static int is_symlink (const char *);
247 static char * chase_symlinks (const char *);
248 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
249 static int restore_privilege (TOKEN_PRIVILEGES
*);
250 static BOOL WINAPI
revert_to_self (void);
252 static int sys_access (const char *, int);
253 extern void *e_malloc (size_t);
254 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
255 struct timespec
*, void *);
256 extern int sys_dup (int);
261 /* Initialization states.
263 WARNING: If you add any more such variables for additional APIs,
264 you MUST add initialization for them to globals_of_w32
265 below. This is because these variables might get set
266 to non-NULL values during dumping, but the dumped Emacs
267 cannot reuse those values, because it could be run on a
268 different version of the OS, where API addresses are
270 static BOOL g_b_init_is_windows_9x
;
271 static BOOL g_b_init_open_process_token
;
272 static BOOL g_b_init_get_token_information
;
273 static BOOL g_b_init_lookup_account_sid
;
274 static BOOL g_b_init_get_sid_sub_authority
;
275 static BOOL g_b_init_get_sid_sub_authority_count
;
276 static BOOL g_b_init_get_security_info
;
277 static BOOL g_b_init_get_file_security_w
;
278 static BOOL g_b_init_get_file_security_a
;
279 static BOOL g_b_init_get_security_descriptor_owner
;
280 static BOOL g_b_init_get_security_descriptor_group
;
281 static BOOL g_b_init_is_valid_sid
;
282 static BOOL g_b_init_create_toolhelp32_snapshot
;
283 static BOOL g_b_init_process32_first
;
284 static BOOL g_b_init_process32_next
;
285 static BOOL g_b_init_open_thread_token
;
286 static BOOL g_b_init_impersonate_self
;
287 static BOOL g_b_init_revert_to_self
;
288 static BOOL g_b_init_get_process_memory_info
;
289 static BOOL g_b_init_get_process_working_set_size
;
290 static BOOL g_b_init_global_memory_status
;
291 static BOOL g_b_init_global_memory_status_ex
;
292 static BOOL g_b_init_get_length_sid
;
293 static BOOL g_b_init_equal_sid
;
294 static BOOL g_b_init_copy_sid
;
295 static BOOL g_b_init_get_native_system_info
;
296 static BOOL g_b_init_get_system_times
;
297 static BOOL g_b_init_create_symbolic_link_w
;
298 static BOOL g_b_init_create_symbolic_link_a
;
299 static BOOL g_b_init_get_security_descriptor_dacl
;
300 static BOOL g_b_init_convert_sd_to_sddl
;
301 static BOOL g_b_init_convert_sddl_to_sd
;
302 static BOOL g_b_init_is_valid_security_descriptor
;
303 static BOOL g_b_init_set_file_security_w
;
304 static BOOL g_b_init_set_file_security_a
;
305 static BOOL g_b_init_get_adapters_info
;
308 BEGIN: Wrapper functions around OpenProcessToken
309 and other functions in advapi32.dll that are only
310 supported in Windows NT / 2k / XP
312 /* ** Function pointer typedefs ** */
313 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
314 HANDLE ProcessHandle
,
316 PHANDLE TokenHandle
);
317 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
319 TOKEN_INFORMATION_CLASS TokenInformationClass
,
320 LPVOID TokenInformation
,
321 DWORD TokenInformationLength
,
322 PDWORD ReturnLength
);
323 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
324 HANDLE process_handle
,
325 LPFILETIME creation_time
,
326 LPFILETIME exit_time
,
327 LPFILETIME kernel_time
,
328 LPFILETIME user_time
);
330 GetProcessTimes_Proc get_process_times_fn
= NULL
;
333 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
335 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
337 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
338 LPCTSTR lpSystemName
,
343 LPDWORD cbDomainName
,
344 PSID_NAME_USE peUse
);
345 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
348 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
350 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
352 SE_OBJECT_TYPE ObjectType
,
353 SECURITY_INFORMATION SecurityInfo
,
358 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
359 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
361 SECURITY_INFORMATION RequestedInformation
,
362 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
364 LPDWORD lpnLengthNeeded
);
365 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
367 SECURITY_INFORMATION RequestedInformation
,
368 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
370 LPDWORD lpnLengthNeeded
);
371 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
373 SECURITY_INFORMATION SecurityInformation
,
374 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
375 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
377 SECURITY_INFORMATION SecurityInformation
,
378 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
379 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
380 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
382 LPBOOL lpbOwnerDefaulted
);
383 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
384 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
386 LPBOOL lpbGroupDefaulted
);
387 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
388 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
389 LPBOOL lpbDaclPresent
,
391 LPBOOL lpbDaclDefaulted
);
392 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
394 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
396 DWORD th32ProcessID
);
397 typedef BOOL (WINAPI
* Process32First_Proc
) (
399 LPPROCESSENTRY32 lppe
);
400 typedef BOOL (WINAPI
* Process32Next_Proc
) (
402 LPPROCESSENTRY32 lppe
);
403 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
407 PHANDLE TokenHandle
);
408 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
409 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
410 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
411 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
413 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
415 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
417 PSIZE_T lpMinimumWorkingSetSize
,
418 PSIZE_T lpMaximumWorkingSetSize
);
419 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
420 LPMEMORYSTATUS lpBuffer
);
421 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
422 LPMEMORY_STATUS_EX lpBuffer
);
423 typedef BOOL (WINAPI
* CopySid_Proc
) (
424 DWORD nDestinationSidLength
,
425 PSID pDestinationSid
,
427 typedef BOOL (WINAPI
* EqualSid_Proc
) (
430 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
432 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
433 LPSYSTEM_INFO lpSystemInfo
);
434 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
435 LPFILETIME lpIdleTime
,
436 LPFILETIME lpKernelTime
,
437 LPFILETIME lpUserTime
);
438 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
439 LPCWSTR lpSymlinkFileName
,
440 LPCWSTR lpTargetFileName
,
442 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
443 LPCSTR lpSymlinkFileName
,
444 LPCSTR lpTargetFileName
,
446 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
447 LPCTSTR StringSecurityDescriptor
,
448 DWORD StringSDRevision
,
449 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
450 PULONG SecurityDescriptorSize
);
451 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
452 PSECURITY_DESCRIPTOR SecurityDescriptor
,
453 DWORD RequestedStringSDRevision
,
454 SECURITY_INFORMATION SecurityInformation
,
455 LPTSTR
*StringSecurityDescriptor
,
456 PULONG StringSecurityDescriptorLen
);
457 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
458 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
459 PIP_ADAPTER_INFO pAdapterInfo
,
462 /* ** A utility function ** */
466 static BOOL s_b_ret
= 0;
467 OSVERSIONINFO os_ver
;
468 if (g_b_init_is_windows_9x
== 0)
470 g_b_init_is_windows_9x
= 1;
471 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
472 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
473 if (GetVersionEx (&os_ver
))
475 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
481 static Lisp_Object
ltime (ULONGLONG
);
483 /* Get total user and system times for get-internal-run-time.
484 Returns a list of integers if the times are provided by the OS
485 (NT derivatives), otherwise it returns the result of current-time. */
487 w32_get_internal_run_time (void)
489 if (get_process_times_fn
)
491 FILETIME create
, exit
, kernel
, user
;
492 HANDLE proc
= GetCurrentProcess ();
493 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
495 LARGE_INTEGER user_int
, kernel_int
, total
;
496 user_int
.LowPart
= user
.dwLowDateTime
;
497 user_int
.HighPart
= user
.dwHighDateTime
;
498 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
499 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
500 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
501 return ltime (total
.QuadPart
);
505 return Fcurrent_time ();
508 /* ** The wrapper functions ** */
511 open_process_token (HANDLE ProcessHandle
,
515 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
516 HMODULE hm_advapi32
= NULL
;
517 if (is_windows_9x () == TRUE
)
521 if (g_b_init_open_process_token
== 0)
523 g_b_init_open_process_token
= 1;
524 hm_advapi32
= LoadLibrary ("Advapi32.dll");
525 s_pfn_Open_Process_Token
=
526 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
528 if (s_pfn_Open_Process_Token
== NULL
)
533 s_pfn_Open_Process_Token (
541 get_token_information (HANDLE TokenHandle
,
542 TOKEN_INFORMATION_CLASS TokenInformationClass
,
543 LPVOID TokenInformation
,
544 DWORD TokenInformationLength
,
547 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
548 HMODULE hm_advapi32
= NULL
;
549 if (is_windows_9x () == TRUE
)
553 if (g_b_init_get_token_information
== 0)
555 g_b_init_get_token_information
= 1;
556 hm_advapi32
= LoadLibrary ("Advapi32.dll");
557 s_pfn_Get_Token_Information
=
558 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
560 if (s_pfn_Get_Token_Information
== NULL
)
565 s_pfn_Get_Token_Information (
567 TokenInformationClass
,
569 TokenInformationLength
,
575 lookup_account_sid (LPCTSTR lpSystemName
,
580 LPDWORD cbDomainName
,
583 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
584 HMODULE hm_advapi32
= NULL
;
585 if (is_windows_9x () == TRUE
)
589 if (g_b_init_lookup_account_sid
== 0)
591 g_b_init_lookup_account_sid
= 1;
592 hm_advapi32
= LoadLibrary ("Advapi32.dll");
593 s_pfn_Lookup_Account_Sid
=
594 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
596 if (s_pfn_Lookup_Account_Sid
== NULL
)
601 s_pfn_Lookup_Account_Sid (
613 get_sid_sub_authority (PSID pSid
, DWORD n
)
615 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
616 static DWORD zero
= 0U;
617 HMODULE hm_advapi32
= NULL
;
618 if (is_windows_9x () == TRUE
)
622 if (g_b_init_get_sid_sub_authority
== 0)
624 g_b_init_get_sid_sub_authority
= 1;
625 hm_advapi32
= LoadLibrary ("Advapi32.dll");
626 s_pfn_Get_Sid_Sub_Authority
=
627 (GetSidSubAuthority_Proc
) GetProcAddress (
628 hm_advapi32
, "GetSidSubAuthority");
630 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
634 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
638 get_sid_sub_authority_count (PSID pSid
)
640 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
641 static UCHAR zero
= 0U;
642 HMODULE hm_advapi32
= NULL
;
643 if (is_windows_9x () == TRUE
)
647 if (g_b_init_get_sid_sub_authority_count
== 0)
649 g_b_init_get_sid_sub_authority_count
= 1;
650 hm_advapi32
= LoadLibrary ("Advapi32.dll");
651 s_pfn_Get_Sid_Sub_Authority_Count
=
652 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
653 hm_advapi32
, "GetSidSubAuthorityCount");
655 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
659 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
663 get_security_info (HANDLE handle
,
664 SE_OBJECT_TYPE ObjectType
,
665 SECURITY_INFORMATION SecurityInfo
,
670 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
672 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
673 HMODULE hm_advapi32
= NULL
;
674 if (is_windows_9x () == TRUE
)
678 if (g_b_init_get_security_info
== 0)
680 g_b_init_get_security_info
= 1;
681 hm_advapi32
= LoadLibrary ("Advapi32.dll");
682 s_pfn_Get_Security_Info
=
683 (GetSecurityInfo_Proc
) GetProcAddress (
684 hm_advapi32
, "GetSecurityInfo");
686 if (s_pfn_Get_Security_Info
== NULL
)
690 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
691 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
692 ppSecurityDescriptor
));
696 get_file_security (const char *lpFileName
,
697 SECURITY_INFORMATION RequestedInformation
,
698 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
700 LPDWORD lpnLengthNeeded
)
702 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
703 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
704 HMODULE hm_advapi32
= NULL
;
705 if (is_windows_9x () == TRUE
)
710 if (w32_unicode_filenames
)
712 wchar_t filename_w
[MAX_PATH
];
714 if (g_b_init_get_file_security_w
== 0)
716 g_b_init_get_file_security_w
= 1;
717 hm_advapi32
= LoadLibrary ("Advapi32.dll");
718 s_pfn_Get_File_SecurityW
=
719 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
722 if (s_pfn_Get_File_SecurityW
== NULL
)
727 filename_to_utf16 (lpFileName
, filename_w
);
728 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
729 pSecurityDescriptor
, nLength
,
734 char filename_a
[MAX_PATH
];
736 if (g_b_init_get_file_security_a
== 0)
738 g_b_init_get_file_security_a
= 1;
739 hm_advapi32
= LoadLibrary ("Advapi32.dll");
740 s_pfn_Get_File_SecurityA
=
741 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
744 if (s_pfn_Get_File_SecurityA
== NULL
)
749 filename_to_ansi (lpFileName
, filename_a
);
750 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
751 pSecurityDescriptor
, nLength
,
757 set_file_security (const char *lpFileName
,
758 SECURITY_INFORMATION SecurityInformation
,
759 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
761 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
762 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
763 HMODULE hm_advapi32
= NULL
;
764 if (is_windows_9x () == TRUE
)
769 if (w32_unicode_filenames
)
771 wchar_t filename_w
[MAX_PATH
];
773 if (g_b_init_set_file_security_w
== 0)
775 g_b_init_set_file_security_w
= 1;
776 hm_advapi32
= LoadLibrary ("Advapi32.dll");
777 s_pfn_Set_File_SecurityW
=
778 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
781 if (s_pfn_Set_File_SecurityW
== NULL
)
786 filename_to_utf16 (lpFileName
, filename_w
);
787 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
788 pSecurityDescriptor
));
792 char filename_a
[MAX_PATH
];
794 if (g_b_init_set_file_security_a
== 0)
796 g_b_init_set_file_security_a
= 1;
797 hm_advapi32
= LoadLibrary ("Advapi32.dll");
798 s_pfn_Set_File_SecurityA
=
799 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
802 if (s_pfn_Set_File_SecurityA
== NULL
)
807 filename_to_ansi (lpFileName
, filename_a
);
808 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
809 pSecurityDescriptor
));
814 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
816 LPBOOL lpbOwnerDefaulted
)
818 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
819 HMODULE hm_advapi32
= NULL
;
820 if (is_windows_9x () == TRUE
)
825 if (g_b_init_get_security_descriptor_owner
== 0)
827 g_b_init_get_security_descriptor_owner
= 1;
828 hm_advapi32
= LoadLibrary ("Advapi32.dll");
829 s_pfn_Get_Security_Descriptor_Owner
=
830 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
831 hm_advapi32
, "GetSecurityDescriptorOwner");
833 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
838 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
843 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
845 LPBOOL lpbGroupDefaulted
)
847 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
848 HMODULE hm_advapi32
= NULL
;
849 if (is_windows_9x () == TRUE
)
854 if (g_b_init_get_security_descriptor_group
== 0)
856 g_b_init_get_security_descriptor_group
= 1;
857 hm_advapi32
= LoadLibrary ("Advapi32.dll");
858 s_pfn_Get_Security_Descriptor_Group
=
859 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
860 hm_advapi32
, "GetSecurityDescriptorGroup");
862 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
867 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
872 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
873 LPBOOL lpbDaclPresent
,
875 LPBOOL lpbDaclDefaulted
)
877 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
878 HMODULE hm_advapi32
= NULL
;
879 if (is_windows_9x () == TRUE
)
884 if (g_b_init_get_security_descriptor_dacl
== 0)
886 g_b_init_get_security_descriptor_dacl
= 1;
887 hm_advapi32
= LoadLibrary ("Advapi32.dll");
888 s_pfn_Get_Security_Descriptor_Dacl
=
889 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
890 hm_advapi32
, "GetSecurityDescriptorDacl");
892 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
897 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
898 lpbDaclPresent
, pDacl
,
903 is_valid_sid (PSID sid
)
905 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
906 HMODULE hm_advapi32
= NULL
;
907 if (is_windows_9x () == TRUE
)
911 if (g_b_init_is_valid_sid
== 0)
913 g_b_init_is_valid_sid
= 1;
914 hm_advapi32
= LoadLibrary ("Advapi32.dll");
916 (IsValidSid_Proc
) GetProcAddress (
917 hm_advapi32
, "IsValidSid");
919 if (s_pfn_Is_Valid_Sid
== NULL
)
923 return (s_pfn_Is_Valid_Sid (sid
));
927 equal_sid (PSID sid1
, PSID sid2
)
929 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
930 HMODULE hm_advapi32
= NULL
;
931 if (is_windows_9x () == TRUE
)
935 if (g_b_init_equal_sid
== 0)
937 g_b_init_equal_sid
= 1;
938 hm_advapi32
= LoadLibrary ("Advapi32.dll");
940 (EqualSid_Proc
) GetProcAddress (
941 hm_advapi32
, "EqualSid");
943 if (s_pfn_Equal_Sid
== NULL
)
947 return (s_pfn_Equal_Sid (sid1
, sid2
));
951 get_length_sid (PSID sid
)
953 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
954 HMODULE hm_advapi32
= NULL
;
955 if (is_windows_9x () == TRUE
)
959 if (g_b_init_get_length_sid
== 0)
961 g_b_init_get_length_sid
= 1;
962 hm_advapi32
= LoadLibrary ("Advapi32.dll");
963 s_pfn_Get_Length_Sid
=
964 (GetLengthSid_Proc
) GetProcAddress (
965 hm_advapi32
, "GetLengthSid");
967 if (s_pfn_Get_Length_Sid
== NULL
)
971 return (s_pfn_Get_Length_Sid (sid
));
975 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
977 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
978 HMODULE hm_advapi32
= NULL
;
979 if (is_windows_9x () == TRUE
)
983 if (g_b_init_copy_sid
== 0)
985 g_b_init_copy_sid
= 1;
986 hm_advapi32
= LoadLibrary ("Advapi32.dll");
988 (CopySid_Proc
) GetProcAddress (
989 hm_advapi32
, "CopySid");
991 if (s_pfn_Copy_Sid
== NULL
)
995 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
999 END: Wrapper functions around OpenProcessToken
1000 and other functions in advapi32.dll that are only
1001 supported in Windows NT / 2k / XP
1005 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1007 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1008 if (is_windows_9x () != TRUE
)
1010 if (g_b_init_get_native_system_info
== 0)
1012 g_b_init_get_native_system_info
= 1;
1013 s_pfn_Get_Native_System_Info
=
1014 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1015 "GetNativeSystemInfo");
1017 if (s_pfn_Get_Native_System_Info
!= NULL
)
1018 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1021 lpSystemInfo
->dwNumberOfProcessors
= -1;
1025 get_system_times (LPFILETIME lpIdleTime
,
1026 LPFILETIME lpKernelTime
,
1027 LPFILETIME lpUserTime
)
1029 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1030 if (is_windows_9x () == TRUE
)
1034 if (g_b_init_get_system_times
== 0)
1036 g_b_init_get_system_times
= 1;
1037 s_pfn_Get_System_times
=
1038 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1041 if (s_pfn_Get_System_times
== NULL
)
1043 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1046 static BOOLEAN WINAPI
1047 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1048 LPCSTR lpTargetFileName
,
1051 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1052 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1055 if (is_windows_9x () == TRUE
)
1060 if (w32_unicode_filenames
)
1062 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1064 if (g_b_init_create_symbolic_link_w
== 0)
1066 g_b_init_create_symbolic_link_w
= 1;
1067 s_pfn_Create_Symbolic_LinkW
=
1068 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1069 "CreateSymbolicLinkW");
1071 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1077 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1078 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1079 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1080 /* If we were denied creation of the symlink, try again after
1081 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1084 TOKEN_PRIVILEGES priv_current
;
1086 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1089 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1090 restore_privilege (&priv_current
);
1097 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1099 if (g_b_init_create_symbolic_link_a
== 0)
1101 g_b_init_create_symbolic_link_a
= 1;
1102 s_pfn_Create_Symbolic_LinkA
=
1103 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1104 "CreateSymbolicLinkA");
1106 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1112 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1113 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1114 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1115 /* If we were denied creation of the symlink, try again after
1116 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1119 TOKEN_PRIVILEGES priv_current
;
1121 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1124 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1125 restore_privilege (&priv_current
);
1134 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1136 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1138 if (is_windows_9x () == TRUE
)
1144 if (g_b_init_is_valid_security_descriptor
== 0)
1146 g_b_init_is_valid_security_descriptor
= 1;
1147 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1148 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1149 "IsValidSecurityDescriptor");
1151 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1157 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1161 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1162 DWORD RequestedStringSDRevision
,
1163 SECURITY_INFORMATION SecurityInformation
,
1164 LPTSTR
*StringSecurityDescriptor
,
1165 PULONG StringSecurityDescriptorLen
)
1167 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1170 if (is_windows_9x () == TRUE
)
1176 if (g_b_init_convert_sd_to_sddl
== 0)
1178 g_b_init_convert_sd_to_sddl
= 1;
1180 s_pfn_Convert_SD_To_SDDL
=
1181 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1182 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1184 s_pfn_Convert_SD_To_SDDL
=
1185 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1186 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1189 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1195 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1196 RequestedStringSDRevision
,
1197 SecurityInformation
,
1198 StringSecurityDescriptor
,
1199 StringSecurityDescriptorLen
);
1205 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1206 DWORD StringSDRevision
,
1207 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1208 PULONG SecurityDescriptorSize
)
1210 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1213 if (is_windows_9x () == TRUE
)
1219 if (g_b_init_convert_sddl_to_sd
== 0)
1221 g_b_init_convert_sddl_to_sd
= 1;
1223 s_pfn_Convert_SDDL_To_SD
=
1224 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1225 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1227 s_pfn_Convert_SDDL_To_SD
=
1228 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1229 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1232 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1238 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1241 SecurityDescriptorSize
);
1247 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1249 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1250 HMODULE hm_iphlpapi
= NULL
;
1252 if (is_windows_9x () == TRUE
)
1253 return ERROR_NOT_SUPPORTED
;
1255 if (g_b_init_get_adapters_info
== 0)
1257 g_b_init_get_adapters_info
= 1;
1258 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1260 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1261 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1263 if (s_pfn_Get_Adapters_Info
== NULL
)
1264 return ERROR_NOT_SUPPORTED
;
1265 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1270 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1271 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1273 This is called from alloc.c:valid_pointer_p. */
1275 w32_valid_pointer_p (void *p
, int size
)
1278 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1282 unsigned char *buf
= alloca (size
);
1283 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1294 /* Here's an overview of how the Windows build supports file names
1295 that cannot be encoded by the current system codepage.
1297 From the POV of Lisp and layers of C code above the functions here,
1298 Emacs on Windows pretends that its file names are encoded in UTF-8;
1299 see encode_file and decode_file on coding.c. Any file name that is
1300 passed as a unibyte string to C functions defined here is assumed
1301 to be in UTF-8 encoding. Any file name returned by functions
1302 defined here must be in UTF-8 encoding, with only a few exceptions
1303 reserved for a couple of special cases. (Be sure to use
1304 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1305 as they can be much longer than MAX_PATH!)
1307 The UTF-8 encoded file names cannot be passed to system APIs, as
1308 Windows does not support that. Therefore, they are converted
1309 either to UTF-16 or to the ANSI codepage, depending on the value of
1310 w32-unicode-filenames, before calling any system APIs or CRT library
1311 functions. The default value of that variable is determined by the
1312 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1313 user can change that default (although I don't see why would she
1316 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1317 filename_from_utf16, and filename_from_ansi, are the workhorses of
1318 these conversions. They rely on Windows native APIs
1319 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1320 functions from coding.c here, because they allocate memory, which
1321 is a bad idea on the level of libc, which is what the functions
1322 here emulate. (If you worry about performance due to constant
1323 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1324 it was measured to take only a few microseconds on a not-so-fast
1325 machine, and second, that's exactly what the ANSI APIs we used
1326 before do anyway, because they are just thin wrappers around the
1329 The variables file-name-coding-system and default-file-name-coding-system
1330 still exist, but are actually used only when a file name needs to
1331 be converted to the ANSI codepage. This happens all the time when
1332 w32-unicode-filenames is nil, but can also happen from time to time
1333 when it is t. Otherwise, these variables have no effect on file-name
1334 encoding when w32-unicode-filenames is t; this is similar to
1335 selection-coding-system.
1337 This arrangement works very well, but it has a few gotchas and
1340 . Lisp code that encodes or decodes file names manually should
1341 normally use 'utf-8' as the coding-system on Windows,
1342 disregarding file-name-coding-system. This is a somewhat
1343 unpleasant consequence, but it cannot be avoided. Fortunately,
1344 very few Lisp packages need to do that.
1346 More generally, passing to library functions (e.g., fopen or
1347 opendir) file names already encoded in the ANSI codepage is
1348 explicitly *verboten*, as all those functions, as shadowed and
1349 emulated here, assume they will receive UTF-8 encoded file names.
1351 For the same reasons, no CRT function or Win32 API can be called
1352 directly in Emacs sources, without either converting the file
1353 name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
1354 through some shadowing function defined here.
1356 . Environment variables stored in Vprocess_environment are encoded
1357 in the ANSI codepage, so if getenv/egetenv is used for a variable
1358 whose value is a file name or a list of directories, it needs to
1359 be converted to UTF-8, before it is used as argument to functions
1360 or decoded into a Lisp string.
1362 . File names passed to external libraries, like the image libraries
1363 and GnuTLS, need special handling. These libraries generally
1364 don't support UTF-16 or UTF-8 file names, so they must get file
1365 names encoded in the ANSI codepage. To facilitate using these
1366 libraries with file names that are not encodable in the ANSI
1367 codepage, use the function ansi_encode_filename, which will try
1368 to use the short 8+3 alias of a file name if that file name is
1369 not encodable in the ANSI codepage. See image.c and gnutls.c for
1370 examples of how this should be done.
1372 . Running subprocesses in non-ASCII directories and with non-ASCII
1373 file arguments is limited to the current codepage (even though
1374 Emacs is perfectly capable of finding an executable program file
1375 even in a directory whose name cannot be encoded in the current
1376 codepage). This is because the command-line arguments are
1377 encoded _before_ they get to the w32-specific level, and the
1378 encoding is not known in advance (it doesn't have to be the
1379 current ANSI codepage), so w32proc.c functions cannot re-encode
1380 them in UTF-16. This should be fixed, but will also require
1381 changes in cmdproxy. The current limitation is not terribly bad
1382 anyway, since very few, if any, Windows console programs that are
1383 likely to be invoked by Emacs support UTF-16 encoded command
1386 . For similar reasons, server.el and emacsclient are also limited
1387 to the current ANSI codepage for now.
1389 . Emacs itself can only handle command-line arguments encoded in
1390 the current codepage.
1392 . Turning on w32-unicode-filename on Windows 9X (if it at all
1393 works) requires UNICOWS.DLL, which is currently loaded only in a
1398 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1399 codepage defined by file-name-coding-system. */
1401 /* Current codepage for encoding file names. */
1402 static int file_name_codepage
;
1404 /* Produce a Windows ANSI codepage suitable for encoding file names.
1405 Return the information about that codepage in CP_INFO. */
1407 codepage_for_filenames (CPINFO
*cp_info
)
1409 /* A simple cache to avoid calling GetCPInfo every time we need to
1410 encode/decode a file name. The file-name encoding is not
1411 supposed to be changed too frequently, if ever. */
1412 static Lisp_Object last_file_name_encoding
;
1414 Lisp_Object current_encoding
;
1416 current_encoding
= Vfile_name_coding_system
;
1417 if (NILP (current_encoding
))
1418 current_encoding
= Vdefault_file_name_coding_system
;
1420 if (!EQ (last_file_name_encoding
, current_encoding
))
1422 /* Default to the current ANSI codepage. */
1423 file_name_codepage
= w32_ansi_code_page
;
1425 if (NILP (current_encoding
))
1427 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1428 char *cp
= NULL
, *end
;
1431 if (strncmp (cpname
, "cp", 2) == 0)
1433 else if (strncmp (cpname
, "windows-", 8) == 0)
1439 cpnum
= strtol (cp
, &end
, 10);
1440 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1441 file_name_codepage
= cpnum
;
1445 if (!file_name_codepage
)
1446 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1448 if (!GetCPInfo (file_name_codepage
, &cp
))
1450 file_name_codepage
= CP_ACP
;
1451 if (!GetCPInfo (file_name_codepage
, &cp
))
1458 return file_name_codepage
;
1462 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1464 int result
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1469 DWORD err
= GetLastError ();
1473 case ERROR_INVALID_FLAGS
:
1474 case ERROR_INVALID_PARAMETER
:
1477 case ERROR_INSUFFICIENT_BUFFER
:
1478 case ERROR_NO_UNICODE_TRANSLATION
:
1489 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1491 int result
= WideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1492 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1496 DWORD err
= GetLastError ();
1500 case ERROR_INVALID_FLAGS
:
1501 case ERROR_INVALID_PARAMETER
:
1504 case ERROR_INSUFFICIENT_BUFFER
:
1505 case ERROR_NO_UNICODE_TRANSLATION
:
1516 filename_to_ansi (const char *fn_in
, char *fn_out
)
1518 wchar_t fn_utf16
[MAX_PATH
];
1520 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1523 int codepage
= codepage_for_filenames (NULL
);
1525 result
= WideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1526 fn_out
, MAX_PATH
, NULL
, NULL
);
1529 DWORD err
= GetLastError ();
1533 case ERROR_INVALID_FLAGS
:
1534 case ERROR_INVALID_PARAMETER
:
1537 case ERROR_INSUFFICIENT_BUFFER
:
1538 case ERROR_NO_UNICODE_TRANSLATION
:
1551 filename_from_ansi (const char *fn_in
, char *fn_out
)
1553 wchar_t fn_utf16
[MAX_PATH
];
1554 int codepage
= codepage_for_filenames (NULL
);
1555 int result
= MultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1556 fn_utf16
, MAX_PATH
);
1560 DWORD err
= GetLastError ();
1564 case ERROR_INVALID_FLAGS
:
1565 case ERROR_INVALID_PARAMETER
:
1568 case ERROR_INSUFFICIENT_BUFFER
:
1569 case ERROR_NO_UNICODE_TRANSLATION
:
1576 return filename_from_utf16 (fn_utf16
, fn_out
);
1581 /* The directory where we started, in UTF-8. */
1582 static char startup_dir
[MAX_UTF8_PATH
];
1584 /* Get the current working directory. */
1586 getcwd (char *dir
, int dirsize
)
1593 if (dirsize
<= strlen (startup_dir
))
1599 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1603 /* Emacs doesn't actually change directory itself, it stays in the
1604 same directory where it was started. */
1605 strcpy (dir
, startup_dir
);
1610 /* Emulate getloadavg. */
1612 struct load_sample
{
1619 /* Number of processors on this machine. */
1620 static unsigned num_of_processors
;
1622 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1623 static struct load_sample samples
[16*60];
1624 static int first_idx
= -1, last_idx
= -1;
1625 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1630 int next_idx
= from
+ 1;
1632 if (next_idx
>= max_idx
)
1641 int prev_idx
= from
- 1;
1644 prev_idx
= max_idx
- 1;
1650 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1652 SYSTEM_INFO sysinfo
;
1653 FILETIME ft_idle
, ft_user
, ft_kernel
;
1655 /* Initialize the number of processors on this machine. */
1656 if (num_of_processors
<= 0)
1658 get_native_system_info (&sysinfo
);
1659 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1660 if (num_of_processors
<= 0)
1662 GetSystemInfo (&sysinfo
);
1663 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1665 if (num_of_processors
<= 0)
1666 num_of_processors
= 1;
1669 /* TODO: Take into account threads that are ready to run, by
1670 sampling the "\System\Processor Queue Length" performance
1671 counter. The code below accounts only for threads that are
1672 actually running. */
1674 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1676 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1678 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1679 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1680 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1681 *idle
= uidle
.QuadPart
;
1682 *kernel
= ukernel
.QuadPart
;
1683 *user
= uuser
.QuadPart
;
1693 /* Produce the load average for a given time interval, using the
1694 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1695 1-minute, 5-minute, or 15-minute average, respectively. */
1699 double retval
= -1.0;
1702 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1703 time_t now
= samples
[last_idx
].sample_time
;
1705 if (first_idx
!= last_idx
)
1707 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1709 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1710 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1713 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1714 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1715 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1717 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1720 if (idx
== first_idx
)
1729 getloadavg (double loadavg
[], int nelem
)
1732 ULONGLONG idle
, kernel
, user
;
1733 time_t now
= time (NULL
);
1735 /* Store another sample. We ignore samples that are less than 1 sec
1737 if (difftime (now
, samples
[last_idx
].sample_time
) >= 1.0 - 2*DBL_EPSILON
*now
)
1739 sample_system_load (&idle
, &kernel
, &user
);
1740 last_idx
= buf_next (last_idx
);
1741 samples
[last_idx
].sample_time
= now
;
1742 samples
[last_idx
].idle
= idle
;
1743 samples
[last_idx
].kernel
= kernel
;
1744 samples
[last_idx
].user
= user
;
1745 /* If the buffer has more that 15 min worth of samples, discard
1747 if (first_idx
== -1)
1748 first_idx
= last_idx
;
1749 while (first_idx
!= last_idx
1750 && (difftime (now
, samples
[first_idx
].sample_time
)
1751 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1752 first_idx
= buf_next (first_idx
);
1755 for (elem
= 0; elem
< nelem
; elem
++)
1757 double avg
= getavg (elem
);
1761 loadavg
[elem
] = avg
;
1767 /* Emulate getpwuid, getpwnam and others. */
1769 #define PASSWD_FIELD_SIZE 256
1771 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1772 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1773 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1774 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1775 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1777 static struct passwd dflt_passwd
=
1789 static char dflt_group_name
[GNLEN
+1];
1791 static struct group dflt_group
=
1793 /* When group information is not available, we return this as the
1794 group for all files. */
1802 return dflt_passwd
.pw_uid
;
1808 /* I could imagine arguing for checking to see whether the user is
1809 in the Administrators group and returning a UID of 0 for that
1810 case, but I don't know how wise that would be in the long run. */
1817 return dflt_passwd
.pw_gid
;
1827 getpwuid (unsigned uid
)
1829 if (uid
== dflt_passwd
.pw_uid
)
1830 return &dflt_passwd
;
1835 getgrgid (gid_t gid
)
1841 getpwnam (char *name
)
1845 pw
= getpwuid (getuid ());
1849 if (xstrcasecmp (name
, pw
->pw_name
))
1856 init_user_info (void)
1858 /* Find the user's real name by opening the process token and
1859 looking up the name associated with the user-sid in that token.
1861 Use the relative portion of the identifier authority value from
1862 the user-sid as the user id value (same for group id using the
1863 primary group sid from the process token). */
1865 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1866 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1867 DWORD glength
= sizeof (gname
);
1868 HANDLE token
= NULL
;
1869 SID_NAME_USE user_type
;
1870 unsigned char *buf
= NULL
;
1872 TOKEN_USER user_token
;
1873 TOKEN_PRIMARY_GROUP group_token
;
1876 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1879 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1880 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1882 buf
= xmalloc (blen
);
1883 result
= get_token_information (token
, TokenUser
,
1884 (LPVOID
)buf
, blen
, &needed
);
1887 memcpy (&user_token
, buf
, sizeof (user_token
));
1888 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1890 domain
, &dlength
, &user_type
);
1898 strcpy (dflt_passwd
.pw_name
, uname
);
1899 /* Determine a reasonable uid value. */
1900 if (xstrcasecmp ("administrator", uname
) == 0)
1902 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
1903 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
1907 /* Use the last sub-authority value of the RID, the relative
1908 portion of the SID, as user/group ID. */
1909 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
1911 /* Get group id and name. */
1912 result
= get_token_information (token
, TokenPrimaryGroup
,
1913 (LPVOID
)buf
, blen
, &needed
);
1914 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1916 buf
= xrealloc (buf
, blen
= needed
);
1917 result
= get_token_information (token
, TokenPrimaryGroup
,
1918 (LPVOID
)buf
, blen
, &needed
);
1922 memcpy (&group_token
, buf
, sizeof (group_token
));
1923 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
1924 dlength
= sizeof (domain
);
1925 /* If we can get at the real Primary Group name, use that.
1926 Otherwise, the default group name was already set to
1927 "None" in globals_of_w32. */
1928 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
1929 gname
, &glength
, NULL
, &dlength
,
1931 strcpy (dflt_group_name
, gname
);
1934 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1937 /* If security calls are not supported (presumably because we
1938 are running under Windows 9X), fallback to this: */
1939 else if (GetUserName (uname
, &ulength
))
1941 strcpy (dflt_passwd
.pw_name
, uname
);
1942 if (xstrcasecmp ("administrator", uname
) == 0)
1943 dflt_passwd
.pw_uid
= 0;
1945 dflt_passwd
.pw_uid
= 123;
1946 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1950 strcpy (dflt_passwd
.pw_name
, "unknown");
1951 dflt_passwd
.pw_uid
= 123;
1952 dflt_passwd
.pw_gid
= 123;
1954 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
1956 /* Set dir and shell from environment variables. */
1957 if (w32_unicode_filenames
)
1959 wchar_t *home
= _wgetenv (L
"HOME");
1960 wchar_t *shell
= _wgetenv (L
"SHELL");
1962 /* Ensure HOME and SHELL are defined. */
1967 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
1968 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
1972 char *home
= getenv ("HOME");
1973 char *shell
= getenv ("SHELL");
1979 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
1980 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
1985 CloseHandle (token
);
1991 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
1992 return ((rand () << 15) | rand ());
2001 /* Return the maximum length in bytes of a multibyte character
2002 sequence encoded in the current ANSI codepage. This is required to
2003 correctly walk the encoded file names one character at a time. */
2005 max_filename_mbslen (void)
2009 codepage_for_filenames (&cp_info
);
2010 return cp_info
.MaxCharSize
;
2013 /* Normalize filename by converting in-place all of its path
2014 separators to the separator specified by PATH_SEP. */
2017 normalize_filename (register char *fp
, char path_sep
)
2021 /* Always lower-case drive letters a-z, even if the filesystem
2022 preserves case in filenames.
2023 This is so filenames can be compared by string comparison
2024 functions that are case-sensitive. Even case-preserving filesystems
2025 do not distinguish case in drive letters. */
2028 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2036 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2042 /* Destructively turn backslashes into slashes. */
2044 dostounix_filename (register char *p
)
2046 normalize_filename (p
, '/');
2049 /* Destructively turn slashes into backslashes. */
2051 unixtodos_filename (register char *p
)
2053 normalize_filename (p
, '\\');
2056 /* Remove all CR's that are followed by a LF.
2057 (From msdos.c...probably should figure out a way to share it,
2058 although this code isn't going to ever change.) */
2060 crlf_to_lf (register int n
, register unsigned char *buf
)
2062 unsigned char *np
= buf
;
2063 unsigned char *startp
= buf
;
2064 unsigned char *endp
= buf
+ n
;
2068 while (buf
< endp
- 1)
2072 if (*(++buf
) != 0x0a)
2083 /* Parse the root part of file name, if present. Return length and
2084 optionally store pointer to char after root. */
2086 parse_root (const char * name
, const char ** pPath
)
2088 const char * start
= name
;
2093 /* find the root name of the volume if given */
2094 if (isalpha (name
[0]) && name
[1] == ':')
2096 /* skip past drive specifier */
2098 if (IS_DIRECTORY_SEP (name
[0]))
2101 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2108 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2113 if (IS_DIRECTORY_SEP (name
[0]))
2120 return name
- start
;
2123 /* Get long base name for name; name is assumed to be absolute. */
2125 get_long_basename (char * name
, char * buf
, int size
)
2127 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2128 char fname_utf8
[MAX_UTF8_PATH
];
2132 /* Must be valid filename, no wild cards or other invalid characters. */
2133 if (strpbrk (name
, "*?|<>\""))
2136 if (w32_unicode_filenames
)
2138 wchar_t fname_utf16
[MAX_PATH
];
2139 WIN32_FIND_DATAW find_data_wide
;
2141 filename_to_utf16 (name
, fname_utf16
);
2142 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2143 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2144 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2148 char fname_ansi
[MAX_PATH
];
2149 WIN32_FIND_DATAA find_data_ansi
;
2151 filename_to_ansi (name
, fname_ansi
);
2152 /* If the ANSI name includes ? characters, it is not encodable
2153 in the ANSI codepage. In that case, we deliver the question
2154 marks to the caller; calling FindFirstFileA in this case
2155 could return some unrelated file name in the same
2157 if (_mbspbrk (fname_ansi
, "?"))
2159 /* Find the basename of fname_ansi. */
2160 char *p
= strrchr (fname_ansi
, '\\');
2166 cstatus
= filename_from_ansi (p
, fname_utf8
);
2170 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2171 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2172 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2176 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2177 memcpy (buf
, fname_utf8
, len
+ 1);
2181 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2182 FindClose (dir_handle
);
2187 /* Get long name for file, if possible (assumed to be absolute). */
2189 w32_get_long_filename (char * name
, char * buf
, int size
)
2194 char full
[ MAX_UTF8_PATH
];
2197 len
= strlen (name
);
2198 if (len
>= MAX_UTF8_PATH
)
2201 /* Use local copy for destructive modification. */
2202 memcpy (full
, name
, len
+1);
2203 unixtodos_filename (full
);
2205 /* Copy root part verbatim. */
2206 len
= parse_root (full
, (const char **)&p
);
2207 memcpy (o
, full
, len
);
2212 while (p
!= NULL
&& *p
)
2215 p
= strchr (q
, '\\');
2217 len
= get_long_basename (full
, o
, size
);
2240 w32_get_short_filename (char * name
, char * buf
, int size
)
2242 if (w32_unicode_filenames
)
2244 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2245 unsigned int retval
;
2247 filename_to_utf16 (name
, name_utf16
);
2248 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2249 if (retval
&& retval
< size
)
2250 filename_from_utf16 (short_name
, buf
);
2255 char name_ansi
[MAX_PATH
];
2257 filename_to_ansi (name
, name_ansi
);
2258 return GetShortPathNameA (name_ansi
, buf
, size
);
2262 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2263 MS-Windows ANSI codepage. If FILENAME includes characters not
2264 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2265 if it exists. This is needed because the w32 build wants to
2266 support file names outside of the system locale, but image
2267 libraries typically don't support wide (a.k.a. "Unicode") APIs
2268 required for that. */
2271 ansi_encode_filename (Lisp_Object filename
)
2273 Lisp_Object encoded_filename
;
2274 char fname
[MAX_PATH
];
2276 filename_to_ansi (SSDATA (filename
), fname
);
2277 if (_mbspbrk (fname
, "?"))
2279 char shortname
[MAX_PATH
];
2281 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2283 dostounix_filename (shortname
);
2284 encoded_filename
= build_string (shortname
);
2288 encoded_filename
= build_unibyte_string (fname
);
2289 return encoded_filename
;
2293 is_unc_volume (const char *filename
)
2295 const char *ptr
= filename
;
2297 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2300 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2306 /* Emulate the Posix unsetenv. */
2308 unsetenv (const char *name
)
2314 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2319 name_len
= strlen (name
);
2320 /* MS docs says an environment variable cannot be longer than 32K. */
2321 if (name_len
> 32767)
2326 /* It is safe to use 'alloca' with 32K size, since the stack is at
2327 least 2MB, and we set it to 8MB in the link command line. */
2328 var
= alloca (name_len
+ 2);
2329 strncpy (var
, name
, name_len
);
2330 var
[name_len
++] = '=';
2331 var
[name_len
] = '\0';
2332 return _putenv (var
);
2335 /* MS _putenv doesn't support removing a variable when the argument
2336 does not include the '=' character, so we fix that here. */
2338 sys_putenv (char *str
)
2340 const char *const name_end
= strchr (str
, '=');
2342 if (name_end
== NULL
)
2344 /* Remove the variable from the environment. */
2345 return unsetenv (str
);
2348 return _putenv (str
);
2351 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2354 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2357 HKEY hrootkey
= NULL
;
2360 /* Check both the current user and the local machine to see if
2361 we have any resources. */
2363 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2367 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2368 && (lpvalue
= xmalloc (cbData
)) != NULL
2369 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2371 RegCloseKey (hrootkey
);
2377 RegCloseKey (hrootkey
);
2380 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2384 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2385 && (lpvalue
= xmalloc (cbData
)) != NULL
2386 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2388 RegCloseKey (hrootkey
);
2394 RegCloseKey (hrootkey
);
2400 /* The argv[] array holds ANSI-encoded strings, and so this function
2401 works with ANS_encoded strings. */
2403 init_environment (char ** argv
)
2405 static const char * const tempdirs
[] = {
2406 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2411 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2413 /* Implementation note: This function explicitly works with ANSI
2414 file names, not with UTF-8 encoded file names. This is because
2415 this function pushes variables into the Emacs's environment, and
2416 the environment variables are always assumed to be in the
2417 locale-specific encoding. Do NOT call any functions that accept
2418 UTF-8 file names from this function! */
2420 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2421 temporary files and assume "/tmp" if $TMPDIR is unset, which
2422 will break on DOS/Windows. Refuse to work if we cannot find
2423 a directory, not even "c:/", usable for that purpose. */
2424 for (i
= 0; i
< imax
; i
++)
2426 const char *tmp
= tempdirs
[i
];
2429 tmp
= getenv (tmp
+ 1);
2430 /* Note that `access' can lie to us if the directory resides on a
2431 read-only filesystem, like CD-ROM or a write-protected floppy.
2432 The only way to be really sure is to actually create a file and
2433 see if it succeeds. But I think that's too much to ask. */
2435 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2436 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2438 char * var
= alloca (strlen (tmp
) + 8);
2439 sprintf (var
, "TMPDIR=%s", tmp
);
2440 _putenv (strdup (var
));
2447 Fcons (build_string ("no usable temporary directories found!!"),
2449 "While setting TMPDIR: ");
2451 /* Check for environment variables and use registry settings if they
2452 don't exist. Fallback on default values where applicable. */
2457 char locale_name
[32];
2458 char default_home
[MAX_PATH
];
2461 static const struct env_entry
2467 /* If the default value is NULL, we will use the value from the
2468 outside environment or the Registry, but will not push the
2469 variable into the Emacs environment if it is defined neither
2470 in the Registry nor in the outside environment. */
2472 {"PRELOAD_WINSOCK", NULL
},
2473 {"emacs_dir", "C:/emacs"},
2474 {"EMACSLOADPATH", NULL
},
2475 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2476 {"EMACSDATA", NULL
},
2477 {"EMACSPATH", NULL
},
2484 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2486 /* We need to copy dflt_envvars[] and work on the copy because we
2487 don't want the dumped Emacs to inherit the values of
2488 environment variables we saw during dumping (which could be on
2489 a different system). The defaults above must be left intact. */
2490 struct env_entry env_vars
[N_ENV_VARS
];
2492 for (i
= 0; i
< N_ENV_VARS
; i
++)
2493 env_vars
[i
] = dflt_envvars
[i
];
2495 /* For backwards compatibility, check if a .emacs file exists in C:/
2496 If not, then we can try to default to the appdata directory under the
2497 user's profile, which is more likely to be writable. */
2498 if (sys_access ("C:/.emacs", F_OK
) != 0)
2500 HRESULT profile_result
;
2501 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2502 of Windows 95 and NT4 that have not been updated to include
2504 ShGetFolderPath_fn get_folder_path
;
2505 get_folder_path
= (ShGetFolderPath_fn
)
2506 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2508 if (get_folder_path
!= NULL
)
2510 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2513 /* If we can't get the appdata dir, revert to old behavior. */
2514 if (profile_result
== S_OK
)
2516 env_vars
[0].def_value
= default_home
;
2522 /* Get default locale info and use it for LANG. */
2523 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2524 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2525 locale_name
, sizeof (locale_name
)))
2527 for (i
= 0; i
< N_ENV_VARS
; i
++)
2529 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2531 env_vars
[i
].def_value
= locale_name
;
2537 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2539 /* Treat emacs_dir specially: set it unconditionally based on our
2543 char modname
[MAX_PATH
];
2545 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2547 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2551 if ((p
= _mbsrchr (modname
, '\\'))
2552 /* From bin means installed Emacs, from src means uninstalled. */
2553 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2555 char buf
[SET_ENV_BUF_SIZE
];
2556 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2559 for (p
= modname
; *p
; p
= CharNext (p
))
2560 if (*p
== '\\') *p
= '/';
2562 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2563 _putenv (strdup (buf
));
2564 /* If we are running from the Posix-like build tree, define
2565 SHELL to point to our own cmdproxy. The loop below will
2566 then disregard PATH_EXEC and the default value. */
2567 if (within_build_tree
)
2569 _snprintf (buf
, sizeof (buf
) - 1,
2570 "SHELL=%s/nt/cmdproxy.exe", modname
);
2571 _putenv (strdup (buf
));
2576 for (i
= 0; i
< N_ENV_VARS
; i
++)
2578 if (!getenv (env_vars
[i
].name
))
2581 char bufc
[SET_ENV_BUF_SIZE
];
2583 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2584 /* Also ignore empty environment variables. */
2589 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2591 /* Look for cmdproxy.exe in every directory in
2592 PATH_EXEC. FIXME: This does not find cmdproxy
2593 in nt/ when we run uninstalled. */
2594 char fname
[MAX_PATH
];
2595 const char *pstart
= PATH_EXEC
, *pend
;
2598 pend
= _mbschr (pstart
, ';');
2600 pend
= pstart
+ strlen (pstart
);
2601 /* Be defensive against series of ;;; characters. */
2604 strncpy (fname
, pstart
, pend
- pstart
);
2605 fname
[pend
- pstart
] = '/';
2606 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2607 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2609 if (sys_access (bufc
, F_OK
) == 0)
2622 /* If not found in any directory, use the
2623 default as the last resort. */
2624 lpval
= env_vars
[i
].def_value
;
2625 dwType
= REG_EXPAND_SZ
;
2631 lpval
= env_vars
[i
].def_value
;
2632 dwType
= REG_EXPAND_SZ
;
2634 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2635 Vdelayed_warnings_list
2636 = Fcons (listn (CONSTYPE_HEAP
, 2,
2637 intern ("initialization"),
2638 build_string ("Setting HOME to C:\\ by default is deprecated")),
2639 Vdelayed_warnings_list
);
2644 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2646 if (dwType
== REG_EXPAND_SZ
)
2647 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2648 else if (dwType
== REG_SZ
)
2649 strcpy (buf1
, lpval
);
2650 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2652 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2654 _putenv (strdup (buf2
));
2664 /* Rebuild system configuration to reflect invoking system. */
2665 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2667 /* Another special case: on NT, the PATH variable is actually named
2668 "Path" although cmd.exe (perhaps NT itself) arranges for
2669 environment variable lookup and setting to be case insensitive.
2670 However, Emacs assumes a fully case sensitive environment, so we
2671 need to change "Path" to "PATH" to match the expectations of
2672 various elisp packages. We do this by the sneaky method of
2673 modifying the string in the C runtime environ entry.
2675 The same applies to COMSPEC. */
2679 for (envp
= environ
; *envp
; envp
++)
2680 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2681 memcpy (*envp
, "PATH=", 5);
2682 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2683 memcpy (*envp
, "COMSPEC=", 8);
2686 /* Remember the initial working directory for getcwd. */
2687 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2688 Does it matter anywhere in Emacs? */
2689 if (w32_unicode_filenames
)
2691 wchar_t wstartup_dir
[MAX_PATH
];
2693 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2695 filename_from_utf16 (wstartup_dir
, startup_dir
);
2699 char astartup_dir
[MAX_PATH
];
2701 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2703 filename_from_ansi (astartup_dir
, startup_dir
);
2707 static char modname
[MAX_PATH
];
2709 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2714 /* Determine if there is a middle mouse button, to allow parse_button
2715 to decide whether right mouse events should be mouse-2 or
2717 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2722 /* Called from expand-file-name when default-directory is not a string. */
2725 emacs_root_dir (void)
2727 static char root_dir
[MAX_UTF8_PATH
];
2730 p
= getenv ("emacs_dir");
2733 filename_from_ansi (p
, root_dir
);
2734 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2735 dostounix_filename (root_dir
);
2739 #include <sys/timeb.h>
2741 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2743 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2748 tv
->tv_sec
= tb
.time
;
2749 tv
->tv_usec
= tb
.millitm
* 1000L;
2750 /* Implementation note: _ftime sometimes doesn't update the dstflag
2751 according to the new timezone when the system timezone is
2752 changed. We could fix that by using GetSystemTime and
2753 GetTimeZoneInformation, but that doesn't seem necessary, since
2754 Emacs always calls gettimeofday with the 2nd argument NULL (see
2755 current_emacs_time). */
2758 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2759 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2764 /* Emulate fdutimens. */
2766 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2767 TIMESPEC[0] and TIMESPEC[1], respectively.
2768 FD must be either negative -- in which case it is ignored --
2769 or a file descriptor that is open on FILE.
2770 If FD is nonnegative, then FILE can be NULL, which means
2771 use just futimes instead of utimes.
2772 If TIMESPEC is null, FAIL.
2773 Return 0 on success, -1 (setting errno) on failure. */
2776 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2783 if (fd
< 0 && !file
)
2788 /* _futime's prototype defines 2nd arg as having the type 'struct
2789 _utimbuf', while utime needs to accept 'struct utimbuf' for
2790 compatibility with Posix. So we need to use 2 different (but
2791 equivalent) types to avoid compiler warnings, sigh. */
2794 struct _utimbuf _ut
;
2796 _ut
.actime
= timespec
[0].tv_sec
;
2797 _ut
.modtime
= timespec
[1].tv_sec
;
2798 return _futime (fd
, &_ut
);
2804 ut
.actime
= timespec
[0].tv_sec
;
2805 ut
.modtime
= timespec
[1].tv_sec
;
2806 /* Call 'utime', which is implemented below, not the MS library
2807 function, which fails on directories. */
2808 return utime (file
, &ut
);
2813 /* ------------------------------------------------------------------------- */
2814 /* IO support and wrapper functions for the Windows API. */
2815 /* ------------------------------------------------------------------------- */
2817 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2818 on network directories, so we handle that case here.
2819 (Ulrich Leodolter, 1/11/95). */
2821 sys_ctime (const time_t *t
)
2823 char *str
= (char *) ctime (t
);
2824 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2827 /* Emulate sleep...we could have done this with a define, but that
2828 would necessitate including windows.h in the files that used it.
2829 This is much easier. */
2831 sys_sleep (int seconds
)
2833 Sleep (seconds
* 1000);
2836 /* Internal MSVC functions for low-level descriptor munging */
2837 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2838 extern int __cdecl
_free_osfhnd (int fd
);
2840 /* parallel array of private info on file handles */
2841 filedesc fd_info
[ MAXDESC
];
2843 typedef struct volume_info_data
{
2844 struct volume_info_data
* next
;
2846 /* time when info was obtained */
2849 /* actual volume info */
2858 /* Global referenced by various functions. */
2859 static volume_info_data volume_info
;
2861 /* Vector to indicate which drives are local and fixed (for which cached
2862 data never expires). */
2863 static BOOL fixed_drives
[26];
2865 /* Consider cached volume information to be stale if older than 10s,
2866 at least for non-local drives. Info for fixed drives is never stale. */
2867 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2868 #define VOLINFO_STILL_VALID( root_dir, info ) \
2869 ( ( isalpha (root_dir[0]) && \
2870 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2871 || GetTickCount () - info->timestamp < 10000 )
2873 /* Cache support functions. */
2875 /* Simple linked list with linear search is sufficient. */
2876 static volume_info_data
*volume_cache
= NULL
;
2878 static volume_info_data
*
2879 lookup_volume_info (char * root_dir
)
2881 volume_info_data
* info
;
2883 for (info
= volume_cache
; info
; info
= info
->next
)
2884 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2890 add_volume_info (char * root_dir
, volume_info_data
* info
)
2892 info
->root_dir
= xstrdup (root_dir
);
2893 unixtodos_filename (info
->root_dir
);
2894 info
->next
= volume_cache
;
2895 volume_cache
= info
;
2899 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2900 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2901 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2902 static volume_info_data
*
2903 GetCachedVolumeInformation (char * root_dir
)
2905 volume_info_data
* info
;
2906 char default_root
[ MAX_UTF8_PATH
];
2907 char name
[MAX_PATH
+1];
2908 char type
[MAX_PATH
+1];
2910 /* NULL for root_dir means use root from current directory. */
2911 if (root_dir
== NULL
)
2913 if (w32_unicode_filenames
)
2915 wchar_t curdirw
[MAX_PATH
];
2917 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
2919 filename_from_utf16 (curdirw
, default_root
);
2923 char curdira
[MAX_PATH
];
2925 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
2927 filename_from_ansi (curdira
, default_root
);
2929 parse_root (default_root
, (const char **)&root_dir
);
2931 root_dir
= default_root
;
2934 /* Local fixed drives can be cached permanently. Removable drives
2935 cannot be cached permanently, since the volume name and serial
2936 number (if nothing else) can change. Remote drives should be
2937 treated as if they are removable, since there is no sure way to
2938 tell whether they are or not. Also, the UNC association of drive
2939 letters mapped to remote volumes can be changed at any time (even
2940 by other processes) without notice.
2942 As a compromise, so we can benefit from caching info for remote
2943 volumes, we use a simple expiry mechanism to invalidate cache
2944 entries that are more than ten seconds old. */
2947 /* No point doing this, because WNetGetConnection is even slower than
2948 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2949 GetDriveType is about the only call of this type which does not
2950 involve network access, and so is extremely quick). */
2952 /* Map drive letter to UNC if remote. */
2953 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2955 char remote_name
[ 256 ];
2956 char drive
[3] = { root_dir
[0], ':' };
2958 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2960 /* do something */ ;
2964 info
= lookup_volume_info (root_dir
);
2966 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2972 /* Info is not cached, or is stale. */
2973 if (w32_unicode_filenames
)
2975 wchar_t root_w
[MAX_PATH
];
2976 wchar_t name_w
[MAX_PATH
+1];
2977 wchar_t type_w
[MAX_PATH
+1];
2979 filename_to_utf16 (root_dir
, root_w
);
2980 if (!GetVolumeInformationW (root_w
,
2981 name_w
, sizeof (name_w
),
2985 type_w
, sizeof (type_w
)))
2987 /* Hmm... not really 100% correct, as these 2 are not file
2989 filename_from_utf16 (name_w
, name
);
2990 filename_from_utf16 (type_w
, type
);
2994 char root_a
[MAX_PATH
];
2995 char name_a
[MAX_PATH
+1];
2996 char type_a
[MAX_PATH
+1];
2998 filename_to_ansi (root_dir
, root_a
);
2999 if (!GetVolumeInformationA (root_a
,
3000 name_a
, sizeof (name_a
),
3004 type_a
, sizeof (type_a
)))
3006 filename_from_ansi (name_a
, name
);
3007 filename_from_ansi (type_a
, type
);
3010 /* Cache the volume information for future use, overwriting existing
3011 entry if present. */
3014 info
= xmalloc (sizeof (volume_info_data
));
3015 add_volume_info (root_dir
, info
);
3023 info
->name
= xstrdup (name
);
3024 unixtodos_filename (info
->name
);
3025 info
->serialnum
= serialnum
;
3026 info
->maxcomp
= maxcomp
;
3027 info
->flags
= flags
;
3028 info
->type
= xstrdup (type
);
3029 info
->timestamp
= GetTickCount ();
3035 /* Get information on the volume where NAME is held; set path pointer to
3036 start of pathname in NAME (past UNC header\volume header if present),
3037 if pPath is non-NULL.
3039 Note: if NAME includes symlinks, the information is for the volume
3040 of the symlink, not of its target. That's because, even though
3041 GetVolumeInformation returns information about the symlink target
3042 of its argument, we only pass the root directory to
3043 GetVolumeInformation, not the full NAME. */
3045 get_volume_info (const char * name
, const char ** pPath
)
3047 char temp
[MAX_UTF8_PATH
];
3048 char *rootname
= NULL
; /* default to current volume */
3049 volume_info_data
* info
;
3050 int root_len
= parse_root (name
, pPath
);
3055 /* Copy the root name of the volume, if given. */
3058 strncpy (temp
, name
, root_len
);
3059 temp
[root_len
] = '\0';
3060 unixtodos_filename (temp
);
3064 info
= GetCachedVolumeInformation (rootname
);
3067 /* Set global referenced by other functions. */
3068 volume_info
= *info
;
3074 /* Determine if volume is FAT format (ie. only supports short 8.3
3075 names); also set path pointer to start of pathname in name, if
3076 pPath is non-NULL. */
3078 is_fat_volume (const char * name
, const char ** pPath
)
3080 if (get_volume_info (name
, pPath
))
3081 return (volume_info
.maxcomp
== 12);
3085 /* Convert all slashes in a filename to backslashes, and map filename
3086 to a valid 8.3 name if necessary. The result is a pointer to a
3087 static buffer, so CAVEAT EMPTOR! */
3089 map_w32_filename (const char * name
, const char ** pPath
)
3091 static char shortname
[MAX_UTF8_PATH
];
3092 char * str
= shortname
;
3095 const char * save_name
= name
;
3097 if (strlen (name
) >= sizeof (shortname
))
3099 /* Return a filename which will cause callers to fail. */
3100 strcpy (shortname
, "?");
3104 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3106 register int left
= 8; /* maximum number of chars in part */
3107 register int extn
= 0; /* extension added? */
3108 register int dots
= 2; /* maximum number of dots allowed */
3111 *str
++ = *name
++; /* skip past UNC header */
3113 while ((c
= *name
++))
3120 *str
++ = (c
== ':' ? ':' : '\\');
3121 extn
= 0; /* reset extension flags */
3122 dots
= 2; /* max 2 dots */
3123 left
= 8; /* max length 8 for main part */
3128 /* Convert path components of the form .xxx to _xxx,
3129 but leave . and .. as they are. This allows .emacs
3130 to be read as _emacs, for example. */
3134 IS_DIRECTORY_SEP (*name
))
3149 extn
= 1; /* we've got an extension */
3150 left
= 3; /* 3 chars in extension */
3154 /* any embedded dots after the first are converted to _ */
3159 case '#': /* don't lose these, they're important */
3161 str
[-1] = c
; /* replace last character of part */
3164 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3166 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3168 dots
= 0; /* started a path component */
3177 strcpy (shortname
, name
);
3178 unixtodos_filename (shortname
);
3182 *pPath
= shortname
+ (path
- save_name
);
3188 is_exec (const char * name
)
3190 char * p
= strrchr (name
, '.');
3193 && (xstrcasecmp (p
, ".exe") == 0 ||
3194 xstrcasecmp (p
, ".com") == 0 ||
3195 xstrcasecmp (p
, ".bat") == 0 ||
3196 xstrcasecmp (p
, ".cmd") == 0));
3199 /* Emulate the Unix directory procedures opendir, closedir, and
3200 readdir. We rename them to sys_* names because some versions of
3201 MinGW startup code call opendir and readdir to glob wildcards, and
3202 the code that calls them doesn't grok UTF-8 encoded file names we
3203 produce in dirent->d_name[]. */
3205 struct dirent dir_static
; /* simulated directory contents */
3206 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3207 static int dir_is_fat
;
3208 static char dir_pathname
[MAX_UTF8_PATH
];
3209 static WIN32_FIND_DATAW dir_find_data_w
;
3210 static WIN32_FIND_DATAA dir_find_data_a
;
3211 #define DIR_FIND_DATA_W 1
3212 #define DIR_FIND_DATA_A 2
3213 static int last_dir_find_data
= -1;
3215 /* Support shares on a network resource as subdirectories of a read-only
3217 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3218 static HANDLE
open_unc_volume (const char *);
3219 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3220 static void close_unc_volume (HANDLE
);
3223 sys_opendir (const char *filename
)
3227 /* Opening is done by FindFirstFile. However, a read is inherent to
3228 this operation, so we defer the open until read time. */
3230 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3232 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3235 /* Note: We don't support traversal of UNC volumes via symlinks.
3236 Doing so would mean punishing 99.99% of use cases by resolving
3237 all the possible symlinks in FILENAME, recursively. */
3238 if (is_unc_volume (filename
))
3240 wnet_enum_handle
= open_unc_volume (filename
);
3241 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3245 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3252 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3253 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3254 /* Note: We don't support symlinks to file names on FAT volumes.
3255 Doing so would mean punishing 99.99% of use cases by resolving
3256 all the possible symlinks in FILENAME, recursively. */
3257 dir_is_fat
= is_fat_volume (filename
, NULL
);
3263 sys_closedir (DIR *dirp
)
3265 /* If we have a find-handle open, close it. */
3266 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3268 FindClose (dir_find_handle
);
3269 dir_find_handle
= INVALID_HANDLE_VALUE
;
3271 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3273 close_unc_volume (wnet_enum_handle
);
3274 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3276 xfree ((char *) dirp
);
3280 sys_readdir (DIR *dirp
)
3282 int downcase
= !NILP (Vw32_downcase_file_names
);
3284 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3286 if (!read_unc_volume (wnet_enum_handle
,
3287 dir_find_data_w
.cFileName
,
3288 dir_find_data_a
.cFileName
,
3292 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3293 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3295 char filename
[MAX_UTF8_PATH
+ 2];
3298 strcpy (filename
, dir_pathname
);
3299 ln
= strlen (filename
) - 1;
3300 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3301 strcat (filename
, "\\");
3302 strcat (filename
, "*");
3304 /* Note: No need to resolve symlinks in FILENAME, because
3305 FindFirst opens the directory that is the target of a
3307 if (w32_unicode_filenames
)
3309 wchar_t fnw
[MAX_PATH
];
3311 filename_to_utf16 (filename
, fnw
);
3312 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3318 filename_to_ansi (filename
, fna
);
3319 /* If FILENAME is not representable by the current ANSI
3320 codepage, we don't want FindFirstFileA to interpret the
3321 '?' characters as a wildcard. */
3322 if (_mbspbrk (fna
, "?"))
3323 dir_find_handle
= INVALID_HANDLE_VALUE
;
3325 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3328 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3331 else if (w32_unicode_filenames
)
3333 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3338 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3342 /* Emacs never uses this value, so don't bother making it match
3343 value returned by stat(). */
3344 dir_static
.d_ino
= 1;
3346 if (w32_unicode_filenames
)
3348 if (downcase
|| dir_is_fat
)
3350 wchar_t tem
[MAX_PATH
];
3352 wcscpy (tem
, dir_find_data_w
.cFileName
);
3354 filename_from_utf16 (tem
, dir_static
.d_name
);
3357 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3358 last_dir_find_data
= DIR_FIND_DATA_W
;
3364 /* If the file name in cFileName[] includes `?' characters, it
3365 means the original file name used characters that cannot be
3366 represented by the current ANSI codepage. To avoid total
3367 lossage, retrieve the short 8+3 alias of the long file
3369 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3371 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3372 /* 8+3 aliases are returned in all caps, which could break
3373 various alists that look at filenames' extensions. */
3376 else if (downcase
|| dir_is_fat
)
3377 strcpy (tem
, dir_find_data_a
.cFileName
);
3379 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3380 if (downcase
|| dir_is_fat
)
3383 filename_from_ansi (tem
, dir_static
.d_name
);
3385 last_dir_find_data
= DIR_FIND_DATA_A
;
3388 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3389 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3390 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3396 open_unc_volume (const char *path
)
3398 const char *fn
= map_w32_filename (path
, NULL
);
3402 if (w32_unicode_filenames
)
3405 wchar_t fnw
[MAX_PATH
];
3407 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3408 nrw
.dwType
= RESOURCETYPE_DISK
;
3409 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3410 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3411 nrw
.lpLocalName
= NULL
;
3412 filename_to_utf16 (fn
, fnw
);
3413 nrw
.lpRemoteName
= fnw
;
3414 nrw
.lpComment
= NULL
;
3415 nrw
.lpProvider
= NULL
;
3417 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3418 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3425 nra
.dwScope
= RESOURCE_GLOBALNET
;
3426 nra
.dwType
= RESOURCETYPE_DISK
;
3427 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3428 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3429 nra
.lpLocalName
= NULL
;
3430 filename_to_ansi (fn
, fna
);
3431 nra
.lpRemoteName
= fna
;
3432 nra
.lpComment
= NULL
;
3433 nra
.lpProvider
= NULL
;
3435 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3436 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3438 if (result
== NO_ERROR
)
3441 return INVALID_HANDLE_VALUE
;
3445 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3450 DWORD bufsize
= 512;
3454 if (w32_unicode_filenames
)
3459 buffer
= alloca (bufsize
);
3460 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3461 if (result
!= NO_ERROR
)
3463 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3464 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3466 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3468 wcsncpy (fname_w
, ptrw
, size
);
3473 int dbcs_p
= max_filename_mbslen () > 1;
3476 buffer
= alloca (bufsize
);
3477 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3478 if (result
!= NO_ERROR
)
3480 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3483 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3486 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3487 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3490 strncpy (fname_a
, ptra
, size
);
3498 close_unc_volume (HANDLE henum
)
3500 if (henum
!= INVALID_HANDLE_VALUE
)
3501 WNetCloseEnum (henum
);
3505 unc_volume_file_attributes (const char *path
)
3510 henum
= open_unc_volume (path
);
3511 if (henum
== INVALID_HANDLE_VALUE
)
3514 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3516 close_unc_volume (henum
);
3521 /* Ensure a network connection is authenticated. */
3523 logon_network_drive (const char *path
)
3525 char share
[MAX_UTF8_PATH
];
3532 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3533 drvtype
= DRIVE_REMOTE
;
3534 else if (path
[0] == '\0' || path
[1] != ':')
3535 drvtype
= GetDriveType (NULL
);
3542 drvtype
= GetDriveType (drive
);
3545 /* Only logon to networked drives. */
3546 if (drvtype
!= DRIVE_REMOTE
)
3550 strncpy (share
, path
, MAX_UTF8_PATH
);
3551 /* Truncate to just server and share name. */
3552 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3554 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3561 if (w32_unicode_filenames
)
3563 NETRESOURCEW resourcew
;
3564 wchar_t share_w
[MAX_PATH
];
3566 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3567 resourcew
.dwType
= RESOURCETYPE_DISK
;
3568 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3569 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3570 resourcew
.lpLocalName
= NULL
;
3571 filename_to_utf16 (share
, share_w
);
3572 resourcew
.lpRemoteName
= share_w
;
3573 resourcew
.lpProvider
= NULL
;
3575 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3579 NETRESOURCEA resourcea
;
3580 char share_a
[MAX_PATH
];
3582 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3583 resourcea
.dwType
= RESOURCETYPE_DISK
;
3584 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3585 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3586 resourcea
.lpLocalName
= NULL
;
3587 filename_to_ansi (share
, share_a
);
3588 resourcea
.lpRemoteName
= share_a
;
3589 resourcea
.lpProvider
= NULL
;
3591 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3597 case ERROR_ALREADY_ASSIGNED
:
3599 case ERROR_ACCESS_DENIED
:
3600 case ERROR_LOGON_FAILURE
:
3606 case ERROR_BAD_NET_NAME
:
3607 case ERROR_NO_NET_OR_BAD_PATH
:
3608 case ERROR_NO_NETWORK
:
3609 case ERROR_CANCELLED
:
3616 /* Emulate faccessat(2). */
3618 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3622 if (dirfd
!= AT_FDCWD
3623 && !(IS_DIRECTORY_SEP (path
[0])
3624 || IS_DEVICE_SEP (path
[1])))
3630 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3631 newer versions blow up when passed D_OK. */
3632 path
= map_w32_filename (path
, NULL
);
3633 /* If the last element of PATH is a symlink, we need to resolve it
3634 to get the attributes of its target file. Note: any symlinks in
3635 PATH elements other than the last one are transparently resolved
3636 by GetFileAttributes below. */
3637 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3638 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3639 path
= chase_symlinks (path
);
3641 if (w32_unicode_filenames
)
3643 wchar_t path_w
[MAX_PATH
];
3645 filename_to_utf16 (path
, path_w
);
3646 attributes
= GetFileAttributesW (path_w
);
3650 char path_a
[MAX_PATH
];
3652 filename_to_ansi (path
, path_a
);
3653 attributes
= GetFileAttributesA (path_a
);
3656 if (attributes
== -1)
3658 DWORD w32err
= GetLastError ();
3662 case ERROR_INVALID_NAME
:
3663 case ERROR_BAD_PATHNAME
:
3664 if (is_unc_volume (path
))
3666 attributes
= unc_volume_file_attributes (path
);
3667 if (attributes
== -1)
3675 case ERROR_FILE_NOT_FOUND
:
3676 case ERROR_BAD_NETPATH
:
3685 if ((mode
& X_OK
) != 0
3686 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3691 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3696 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3704 /* A version of 'access' to be used locally with file names in
3705 locale-specific encoding. Does not resolve symlinks and does not
3706 support file names on FAT12 and FAT16 volumes, but that's OK, since
3707 we only invoke this function for files inside the Emacs source or
3708 installation tree, on directories (so any symlinks should have the
3709 directory bit set), and on short file names such as "C:/.emacs". */
3711 sys_access (const char *fname
, int mode
)
3713 char fname_copy
[MAX_PATH
], *p
;
3716 strcpy (fname_copy
, fname
);
3717 /* Do the equivalent of unixtodos_filename. */
3718 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3722 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3724 DWORD w32err
= GetLastError ();
3728 case ERROR_INVALID_NAME
:
3729 case ERROR_BAD_PATHNAME
:
3730 case ERROR_FILE_NOT_FOUND
:
3731 case ERROR_BAD_NETPATH
:
3740 if ((mode
& X_OK
) != 0
3741 && !(is_exec (fname_copy
)
3742 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3747 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3752 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3760 /* Shadow some MSVC runtime functions to map requests for long filenames
3761 to reasonable short names if necessary. This was originally added to
3762 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3766 sys_chdir (const char * path
)
3768 path
= map_w32_filename (path
, NULL
);
3769 if (w32_unicode_filenames
)
3771 wchar_t newdir_w
[MAX_PATH
];
3773 if (filename_to_utf16 (path
, newdir_w
) == 0)
3774 return _wchdir (newdir_w
);
3779 char newdir_a
[MAX_PATH
];
3781 if (filename_to_ansi (path
, newdir_a
) == 0)
3782 return _chdir (newdir_a
);
3788 sys_chmod (const char * path
, int mode
)
3790 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3791 if (w32_unicode_filenames
)
3793 wchar_t path_w
[MAX_PATH
];
3795 filename_to_utf16 (path
, path_w
);
3796 return _wchmod (path_w
, mode
);
3800 char path_a
[MAX_PATH
];
3802 filename_to_ansi (path
, path_a
);
3803 return _chmod (path_a
, mode
);
3808 sys_creat (const char * path
, int mode
)
3810 path
= map_w32_filename (path
, NULL
);
3811 if (w32_unicode_filenames
)
3813 wchar_t path_w
[MAX_PATH
];
3815 filename_to_utf16 (path
, path_w
);
3816 return _wcreat (path_w
, mode
);
3820 char path_a
[MAX_PATH
];
3822 filename_to_ansi (path
, path_a
);
3823 return _creat (path_a
, mode
);
3828 sys_fopen (const char * path
, const char * mode
)
3832 const char * mode_save
= mode
;
3834 /* Force all file handles to be non-inheritable. This is necessary to
3835 ensure child processes don't unwittingly inherit handles that might
3836 prevent future file access. */
3840 else if (mode
[0] == 'w' || mode
[0] == 'a')
3841 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3845 /* Only do simplistic option parsing. */
3849 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3852 else if (mode
[0] == 'b')
3857 else if (mode
[0] == 't')
3864 path
= map_w32_filename (path
, NULL
);
3865 if (w32_unicode_filenames
)
3867 wchar_t path_w
[MAX_PATH
];
3869 filename_to_utf16 (path
, path_w
);
3870 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3874 char path_a
[MAX_PATH
];
3876 filename_to_ansi (path
, path_a
);
3877 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3882 return _fdopen (fd
, mode_save
);
3885 /* This only works on NTFS volumes, but is useful to have. */
3887 sys_link (const char * old
, const char * new)
3891 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3892 wchar_t oldname_w
[MAX_PATH
];
3893 char oldname_a
[MAX_PATH
];
3895 if (old
== NULL
|| new == NULL
)
3901 strcpy (oldname
, map_w32_filename (old
, NULL
));
3902 strcpy (newname
, map_w32_filename (new, NULL
));
3904 if (w32_unicode_filenames
)
3906 filename_to_utf16 (oldname
, oldname_w
);
3907 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
3908 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3912 filename_to_ansi (oldname
, oldname_a
);
3913 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
3914 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3916 if (fileh
!= INVALID_HANDLE_VALUE
)
3920 /* Confusingly, the "alternate" stream name field does not apply
3921 when restoring a hard link, and instead contains the actual
3922 stream data for the link (ie. the name of the link to create).
3923 The WIN32_STREAM_ID structure before the cStreamName field is
3924 the stream header, which is then immediately followed by the
3928 WIN32_STREAM_ID wid
;
3929 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3932 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
3933 indicates that flag is unsupported for CP_UTF8, and OTOH says
3934 it is the default anyway. */
3935 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
3936 data
.wid
.cStreamName
, MAX_PATH
);
3939 LPVOID context
= NULL
;
3942 data
.wid
.dwStreamId
= BACKUP_LINK
;
3943 data
.wid
.dwStreamAttributes
= 0;
3944 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3945 data
.wid
.Size
.HighPart
= 0;
3946 data
.wid
.dwStreamNameSize
= 0;
3948 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3949 offsetof (WIN32_STREAM_ID
, cStreamName
)
3950 + data
.wid
.Size
.LowPart
,
3951 &wbytes
, FALSE
, FALSE
, &context
)
3952 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3959 DWORD err
= GetLastError ();
3964 case ERROR_ACCESS_DENIED
:
3965 /* This is what happens when OLDNAME is a directory,
3966 since Windows doesn't support hard links to
3967 directories. Posix says to set errno to EPERM in
3969 if (w32_unicode_filenames
)
3970 attributes
= GetFileAttributesW (oldname_w
);
3972 attributes
= GetFileAttributesA (oldname_a
);
3973 if (attributes
!= -1
3974 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
3976 else if (attributes
== -1
3977 && is_unc_volume (oldname
)
3978 && unc_volume_file_attributes (oldname
) != -1)
3983 case ERROR_TOO_MANY_LINKS
:
3986 case ERROR_NOT_SAME_DEVICE
:
3996 CloseHandle (fileh
);
4005 sys_mkdir (const char * path
)
4007 path
= map_w32_filename (path
, NULL
);
4009 if (w32_unicode_filenames
)
4011 wchar_t path_w
[MAX_PATH
];
4013 filename_to_utf16 (path
, path_w
);
4014 return _wmkdir (path_w
);
4018 char path_a
[MAX_PATH
];
4020 filename_to_ansi (path
, path_a
);
4021 return _mkdir (path_a
);
4026 sys_open (const char * path
, int oflag
, int mode
)
4028 const char* mpath
= map_w32_filename (path
, NULL
);
4031 if (w32_unicode_filenames
)
4033 wchar_t mpath_w
[MAX_PATH
];
4035 filename_to_utf16 (mpath
, mpath_w
);
4036 /* If possible, try to open file without _O_CREAT, to be able to
4037 write to existing hidden and system files. Force all file
4038 handles to be non-inheritable. */
4039 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4040 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4042 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4046 char mpath_a
[MAX_PATH
];
4048 filename_to_ansi (mpath
, mpath_a
);
4049 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4050 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4052 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4058 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4061 Standard algorithm for generating a temporary file name seems to be
4062 use pid or tid with a letter on the front (in place of the 6 X's)
4063 and cycle through the letters to find a unique name. We extend
4064 that to allow any reasonable character as the first of the 6 X's,
4065 so that the number of simultaneously used temporary files will be
4069 mkostemp (char * template, int flags
)
4073 unsigned uid
= GetCurrentThreadId ();
4074 int save_errno
= errno
;
4075 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4078 if (template == NULL
)
4081 p
= template + strlen (template);
4083 /* replace up to the last 5 X's with uid in decimal */
4084 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4086 p
[0] = '0' + uid
% 10;
4090 if (i
< 0 && p
[0] == 'X')
4095 p
[0] = first_char
[i
];
4096 if ((fd
= sys_open (template,
4097 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4098 S_IRUSR
| S_IWUSR
)) >= 0
4106 while (++i
< sizeof (first_char
));
4109 /* Template is badly formed or else we can't generate a unique name. */
4114 fchmod (int fd
, mode_t mode
)
4120 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4123 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4126 bool have_temp_a
= false;
4128 /* MoveFile on Windows 95 doesn't correctly change the short file name
4129 alias in a number of circumstances (it is not easy to predict when
4130 just by looking at oldname and newname, unfortunately). In these
4131 cases, renaming through a temporary name avoids the problem.
4133 A second problem on Windows 95 is that renaming through a temp name when
4134 newname is uppercase fails (the final long name ends up in
4135 lowercase, although the short alias might be uppercase) UNLESS the
4136 long temp name is not 8.3.
4138 So, on Windows 95 we always rename through a temp name, and we make sure
4139 the temp name has a long extension to ensure correct renaming. */
4141 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4143 /* volume_info is set indirectly by map_w32_filename. */
4144 oldname_dev
= volume_info
.serialnum
;
4146 if (os_subtype
== OS_9X
)
4151 char oldname_a
[MAX_PATH
];
4153 oldname
= map_w32_filename (oldname
, NULL
);
4154 filename_to_ansi (oldname
, oldname_a
);
4155 filename_to_ansi (temp
, temp_a
);
4156 if ((o
= strrchr (oldname_a
, '\\')))
4159 o
= (char *) oldname_a
;
4161 if ((p
= strrchr (temp_a
, '\\')))
4168 /* Force temp name to require a manufactured 8.3 alias - this
4169 seems to make the second rename work properly. */
4170 sprintf (p
, "_.%s.%u", o
, i
);
4172 result
= rename (oldname_a
, temp_a
);
4174 /* This loop must surely terminate! */
4175 while (result
< 0 && errno
== EEXIST
);
4181 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4182 (at least if it is a file; don't do this for directories).
4184 Since we mustn't do this if we are just changing the case of the
4185 file name (we would end up deleting the file we are trying to
4186 rename!), we let rename detect if the destination file already
4187 exists - that way we avoid the possible pitfalls of trying to
4188 determine ourselves whether two names really refer to the same
4189 file, which is not always possible in the general case. (Consider
4190 all the permutations of shared or subst'd drives, etc.) */
4192 newname
= map_w32_filename (newname
, NULL
);
4194 /* volume_info is set indirectly by map_w32_filename. */
4195 newname_dev
= volume_info
.serialnum
;
4197 if (w32_unicode_filenames
)
4199 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4201 filename_to_utf16 (temp
, temp_w
);
4202 filename_to_utf16 (newname
, newname_w
);
4203 result
= _wrename (temp_w
, newname_w
);
4204 if (result
< 0 && force
)
4206 DWORD w32err
= GetLastError ();
4209 && newname_dev
!= oldname_dev
)
4211 /* The implementation of `rename' on Windows does not return
4212 errno = EXDEV when you are moving a directory to a
4213 different storage device (ex. logical disk). It returns
4214 EACCES instead. So here we handle such situations and
4218 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4219 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4222 else if (errno
== EEXIST
)
4224 if (_wchmod (newname_w
, 0666) != 0)
4226 if (_wunlink (newname_w
) != 0)
4228 result
= _wrename (temp_w
, newname_w
);
4230 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4231 && is_symlink (temp
))
4233 /* This is Windows prohibiting the user from creating a
4234 symlink in another place, since that requires
4242 char newname_a
[MAX_PATH
];
4245 filename_to_ansi (temp
, temp_a
);
4246 filename_to_ansi (newname
, newname_a
);
4247 result
= rename (temp_a
, newname_a
);
4248 if (result
< 0 && force
)
4250 DWORD w32err
= GetLastError ();
4253 && newname_dev
!= oldname_dev
)
4257 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4258 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4261 else if (errno
== EEXIST
)
4263 if (_chmod (newname_a
, 0666) != 0)
4265 if (_unlink (newname_a
) != 0)
4267 result
= rename (temp_a
, newname_a
);
4269 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4270 && is_symlink (temp
))
4279 sys_rename (char const *old
, char const *new)
4281 return sys_rename_replace (old
, new, TRUE
);
4285 sys_rmdir (const char * path
)
4287 path
= map_w32_filename (path
, NULL
);
4289 if (w32_unicode_filenames
)
4291 wchar_t path_w
[MAX_PATH
];
4293 filename_to_utf16 (path
, path_w
);
4294 return _wrmdir (path_w
);
4298 char path_a
[MAX_PATH
];
4300 filename_to_ansi (path
, path_a
);
4301 return _rmdir (path_a
);
4306 sys_unlink (const char * path
)
4308 path
= map_w32_filename (path
, NULL
);
4310 if (w32_unicode_filenames
)
4312 wchar_t path_w
[MAX_PATH
];
4314 filename_to_utf16 (path
, path_w
);
4315 /* On Unix, unlink works without write permission. */
4316 _wchmod (path_w
, 0666);
4317 return _wunlink (path_w
);
4321 char path_a
[MAX_PATH
];
4323 filename_to_ansi (path
, path_a
);
4324 _chmod (path_a
, 0666);
4325 return _unlink (path_a
);
4329 static FILETIME utc_base_ft
;
4330 static ULONGLONG utc_base
; /* In 100ns units */
4331 static int init
= 0;
4333 #define FILETIME_TO_U64(result, ft) \
4335 ULARGE_INTEGER uiTemp; \
4336 uiTemp.LowPart = (ft).dwLowDateTime; \
4337 uiTemp.HighPart = (ft).dwHighDateTime; \
4338 result = uiTemp.QuadPart; \
4342 initialize_utc_base (void)
4344 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4353 st
.wMilliseconds
= 0;
4355 SystemTimeToFileTime (&st
, &utc_base_ft
);
4356 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4360 convert_time (FILETIME ft
)
4366 initialize_utc_base ();
4370 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4373 FILETIME_TO_U64 (tmp
, ft
);
4374 return (time_t) ((tmp
- utc_base
) / 10000000L);
4378 convert_from_time_t (time_t time
, FILETIME
* pft
)
4384 initialize_utc_base ();
4388 /* time in 100ns units since 1-Jan-1601 */
4389 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4390 pft
->dwHighDateTime
= tmp
.HighPart
;
4391 pft
->dwLowDateTime
= tmp
.LowPart
;
4394 static PSECURITY_DESCRIPTOR
4395 get_file_security_desc_by_handle (HANDLE h
)
4397 PSECURITY_DESCRIPTOR psd
= NULL
;
4399 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4400 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4402 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4403 NULL
, NULL
, NULL
, NULL
, &psd
);
4404 if (err
!= ERROR_SUCCESS
)
4410 static PSECURITY_DESCRIPTOR
4411 get_file_security_desc_by_name (const char *fname
)
4413 PSECURITY_DESCRIPTOR psd
= NULL
;
4415 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4416 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4418 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4420 err
= GetLastError ();
4421 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4425 psd
= xmalloc (sd_len
);
4426 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4438 unsigned n_subauthorities
;
4440 /* Use the last sub-authority value of the RID, the relative
4441 portion of the SID, as user/group ID. */
4442 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4443 if (n_subauthorities
< 1)
4444 return 0; /* the "World" RID */
4445 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4448 /* Caching SID and account values for faster lokup. */
4452 struct w32_id
*next
;
4454 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4457 static struct w32_id
*w32_idlist
;
4460 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4462 struct w32_id
*tail
, *found
;
4464 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4466 if (equal_sid ((PSID
)tail
->sid
, sid
))
4475 strcpy (name
, found
->name
);
4483 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4486 struct w32_id
*new_entry
;
4488 /* We don't want to leave behind stale cache from when Emacs was
4492 sid_len
= get_length_sid (sid
);
4493 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4496 new_entry
->rid
= id
;
4497 strcpy (new_entry
->name
, name
);
4498 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4499 new_entry
->next
= w32_idlist
;
4500 w32_idlist
= new_entry
;
4509 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4513 SID_NAME_USE ignore
;
4515 DWORD name_len
= sizeof (name
);
4517 DWORD domain_len
= sizeof (domain
);
4522 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4523 else if (what
== GID
)
4524 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4528 if (!result
|| !is_valid_sid (sid
))
4530 else if (!w32_cached_id (sid
, id
, nm
))
4532 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4533 domain
, &domain_len
, &ignore
)
4534 || name_len
> UNLEN
+1)
4538 *id
= get_rid (sid
);
4540 w32_add_to_cache (sid
, *id
, name
);
4547 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4549 int dflt_usr
= 0, dflt_grp
= 0;
4558 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4560 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4563 /* Consider files to belong to current user/group, if we cannot get
4564 more accurate information. */
4567 st
->st_uid
= dflt_passwd
.pw_uid
;
4568 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4572 st
->st_gid
= dflt_passwd
.pw_gid
;
4573 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4577 /* Return non-zero if NAME is a potentially slow filesystem. */
4579 is_slow_fs (const char *name
)
4584 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4585 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4586 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4587 devtype
= GetDriveType (NULL
); /* use root of current drive */
4590 /* GetDriveType needs the root directory of the drive. */
4591 strncpy (drive_root
, name
, 2);
4592 drive_root
[2] = '\\';
4593 drive_root
[3] = '\0';
4594 devtype
= GetDriveType (drive_root
);
4596 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4599 /* If this is non-zero, the caller wants accurate information about
4600 file's owner and group, which could be expensive to get. dired.c
4601 uses this flag when needed for the job at hand. */
4602 int w32_stat_get_owner_group
;
4604 /* MSVC stat function can't cope with UNC names and has other bugs, so
4605 replace it with our own. This also allows us to calculate consistent
4606 inode values and owner/group without hacks in the main Emacs code,
4607 and support file names encoded in UTF-8. */
4610 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4612 char *name
, *save_name
, *r
;
4613 WIN32_FIND_DATAW wfd_w
;
4614 WIN32_FIND_DATAA wfd_a
;
4616 unsigned __int64 fake_inode
= 0;
4619 int rootdir
= FALSE
;
4620 PSECURITY_DESCRIPTOR psd
= NULL
;
4621 int is_a_symlink
= 0;
4622 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4623 DWORD access_rights
= 0;
4624 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4625 FILETIME ctime
, atime
, wtime
;
4626 wchar_t name_w
[MAX_PATH
];
4627 char name_a
[MAX_PATH
];
4629 if (path
== NULL
|| buf
== NULL
)
4635 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4636 /* Must be valid filename, no wild cards or other invalid
4638 if (strpbrk (name
, "*?|<>\""))
4644 /* Remove trailing directory separator, unless name is the root
4645 directory of a drive or UNC volume in which case ensure there
4646 is a trailing separator. */
4647 len
= strlen (name
);
4648 name
= strcpy (alloca (len
+ 2), name
);
4650 /* Avoid a somewhat costly call to is_symlink if the filesystem
4651 doesn't support symlinks. */
4652 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4653 is_a_symlink
= is_symlink (name
);
4655 /* Plan A: Open the file and get all the necessary information via
4656 the resulting handle. This solves several issues in one blow:
4658 . retrieves attributes for the target of a symlink, if needed
4659 . gets attributes of root directories and symlinks pointing to
4660 root directories, thus avoiding the need for special-casing
4661 these and detecting them by examining the file-name format
4662 . retrieves more accurate attributes (e.g., non-zero size for
4663 some directories, esp. directories that are junction points)
4664 . correctly resolves "c:/..", "/.." and similar file names
4665 . avoids run-time penalties for 99% of use cases
4667 Plan A is always tried first, unless the user asked not to (but
4668 if the file is a symlink and we need to follow links, we try Plan
4669 A even if the user asked not to).
4671 If Plan A fails, we go to Plan B (below), where various
4672 potentially expensive techniques must be used to handle "special"
4673 files such as UNC volumes etc. */
4674 if (!(NILP (Vw32_get_true_file_attributes
)
4675 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4676 /* Following symlinks requires getting the info by handle. */
4677 || (is_a_symlink
&& follow_symlinks
))
4679 BY_HANDLE_FILE_INFORMATION info
;
4681 if (is_a_symlink
&& !follow_symlinks
)
4682 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4683 /* READ_CONTROL access rights are required to get security info
4684 by handle. But if the OS doesn't support security in the
4685 first place, we don't need to try. */
4686 if (is_windows_9x () != TRUE
)
4687 access_rights
|= READ_CONTROL
;
4689 if (w32_unicode_filenames
)
4691 filename_to_utf16 (name
, name_w
);
4692 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4694 /* If CreateFile fails with READ_CONTROL, try again with
4695 zero as access rights. */
4696 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4697 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4702 filename_to_ansi (name
, name_a
);
4703 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4705 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4706 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4709 if (fh
== INVALID_HANDLE_VALUE
)
4710 goto no_true_file_attributes
;
4712 /* This is more accurate in terms of getting the correct number
4713 of links, but is quite slow (it is noticeable when Emacs is
4714 making a list of file name completions). */
4715 if (GetFileInformationByHandle (fh
, &info
))
4717 nlinks
= info
.nNumberOfLinks
;
4718 /* Might as well use file index to fake inode values, but this
4719 is not guaranteed to be unique unless we keep a handle open
4720 all the time (even then there are situations where it is
4721 not unique). Reputedly, there are at most 48 bits of info
4722 (on NTFS, presumably less on FAT). */
4723 fake_inode
= info
.nFileIndexHigh
;
4725 fake_inode
+= info
.nFileIndexLow
;
4726 serialnum
= info
.dwVolumeSerialNumber
;
4727 fs_high
= info
.nFileSizeHigh
;
4728 fs_low
= info
.nFileSizeLow
;
4729 ctime
= info
.ftCreationTime
;
4730 atime
= info
.ftLastAccessTime
;
4731 wtime
= info
.ftLastWriteTime
;
4732 fattrs
= info
.dwFileAttributes
;
4736 /* We don't go to Plan B here, because it's not clear that
4737 it's a good idea. The only known use case where
4738 CreateFile succeeds, but GetFileInformationByHandle fails
4739 (with ERROR_INVALID_FUNCTION) is for character devices
4740 such as NUL, PRN, etc. For these, switching to Plan B is
4741 a net loss, because we lose the character device
4742 attribute returned by GetFileType below (FindFirstFile
4743 doesn't set that bit in the attributes), and the other
4744 fields don't make sense for character devices anyway.
4745 Emacs doesn't really care for non-file entities in the
4746 context of l?stat, so neither do we. */
4748 /* w32err is assigned so one could put a breakpoint here and
4749 examine its value, when GetFileInformationByHandle
4751 DWORD w32err
= GetLastError ();
4755 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4761 /* Test for a symlink before testing for a directory, since
4762 symlinks to directories have the directory bit set, but we
4763 don't want them to appear as directories. */
4764 if (is_a_symlink
&& !follow_symlinks
)
4765 buf
->st_mode
= S_IFLNK
;
4766 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4767 buf
->st_mode
= S_IFDIR
;
4770 DWORD ftype
= GetFileType (fh
);
4774 case FILE_TYPE_DISK
:
4775 buf
->st_mode
= S_IFREG
;
4777 case FILE_TYPE_PIPE
:
4778 buf
->st_mode
= S_IFIFO
;
4780 case FILE_TYPE_CHAR
:
4781 case FILE_TYPE_UNKNOWN
:
4783 buf
->st_mode
= S_IFCHR
;
4786 /* We produce the fallback owner and group data, based on the
4787 current user that runs Emacs, in the following cases:
4789 . caller didn't request owner and group info
4790 . this is Windows 9X
4791 . getting security by handle failed, and we need to produce
4792 information for the target of a symlink (this is better
4793 than producing a potentially misleading info about the
4796 If getting security by handle fails, and we don't need to
4797 resolve symlinks, we try getting security by name. */
4798 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4799 get_file_owner_and_group (NULL
, buf
);
4802 psd
= get_file_security_desc_by_handle (fh
);
4805 get_file_owner_and_group (psd
, buf
);
4808 else if (!(is_a_symlink
&& follow_symlinks
))
4810 psd
= get_file_security_desc_by_name (name
);
4811 get_file_owner_and_group (psd
, buf
);
4815 get_file_owner_and_group (NULL
, buf
);
4821 no_true_file_attributes
:
4822 /* Plan B: Either getting a handle on the file failed, or the
4823 caller explicitly asked us to not bother making this
4824 information more accurate.
4826 Implementation note: In Plan B, we never bother to resolve
4827 symlinks, even if we got here because we tried Plan A and
4828 failed. That's because, even if the caller asked for extra
4829 precision by setting Vw32_get_true_file_attributes to t,
4830 resolving symlinks requires acquiring a file handle to the
4831 symlink, which we already know will fail. And if the user
4832 did not ask for extra precision, resolving symlinks will fly
4833 in the face of that request, since the user then wants the
4834 lightweight version of the code. */
4835 rootdir
= (path
>= save_name
+ len
- 1
4836 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4838 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4839 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4840 if (IS_DIRECTORY_SEP (r
[0])
4841 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4844 /* Note: If NAME is a symlink to the root of a UNC volume
4845 (i.e. "\\SERVER"), we will not detect that here, and we will
4846 return data about the symlink as result of FindFirst below.
4847 This is unfortunate, but that marginal use case does not
4848 justify a call to chase_symlinks which would impose a penalty
4849 on all the other use cases. (We get here for symlinks to
4850 roots of UNC volumes because CreateFile above fails for them,
4851 unlike with symlinks to root directories X:\ of drives.) */
4852 if (is_unc_volume (name
))
4854 fattrs
= unc_volume_file_attributes (name
);
4858 ctime
= atime
= wtime
= utc_base_ft
;
4862 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4863 strcat (name
, "\\");
4864 if (GetDriveType (name
) < 2)
4870 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4871 ctime
= atime
= wtime
= utc_base_ft
;
4877 if (IS_DIRECTORY_SEP (name
[len
-1]))
4880 /* (This is hacky, but helps when doing file completions on
4881 network drives.) Optimize by using information available from
4882 active readdir if possible. */
4883 len
= strlen (dir_pathname
);
4884 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4886 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4887 && last_dir_find_data
!= -1
4888 && !(is_a_symlink
&& follow_symlinks
)
4889 /* The 2 file-name comparisons below support only ASCII
4890 characters, and will lose (compare not equal) when
4891 the file names include non-ASCII characters that are
4892 the same but for the case. However, doing this
4893 properly involves: (a) converting both file names to
4894 UTF-16, (b) lower-casing both names using CharLowerW,
4895 and (c) comparing the results; this would be quite a
4896 bit slower, whereas Plan B is for users who want
4897 lightweight albeit inaccurate version of 'stat'. */
4898 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
4899 && IS_DIRECTORY_SEP (name
[len
])
4900 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4902 have_wfd
= last_dir_find_data
;
4903 /* This was the last entry returned by readdir. */
4904 if (last_dir_find_data
== DIR_FIND_DATA_W
)
4905 wfd_w
= dir_find_data_w
;
4907 wfd_a
= dir_find_data_a
;
4911 logon_network_drive (name
);
4913 if (w32_unicode_filenames
)
4915 filename_to_utf16 (name
, name_w
);
4916 fh
= FindFirstFileW (name_w
, &wfd_w
);
4917 have_wfd
= DIR_FIND_DATA_W
;
4921 filename_to_ansi (name
, name_a
);
4922 /* If NAME includes characters not representable by
4923 the current ANSI codepage, filename_to_ansi
4924 usually replaces them with a '?'. We don't want
4925 to let FindFirstFileA interpret those as wildcards,
4926 and "succeed", returning us data from some random
4927 file in the same directory. */
4928 if (_mbspbrk (name_a
, "?"))
4929 fh
= INVALID_HANDLE_VALUE
;
4931 fh
= FindFirstFileA (name_a
, &wfd_a
);
4932 have_wfd
= DIR_FIND_DATA_A
;
4934 if (fh
== INVALID_HANDLE_VALUE
)
4941 /* Note: if NAME is a symlink, the information we get from
4942 FindFirstFile is for the symlink, not its target. */
4943 if (have_wfd
== DIR_FIND_DATA_W
)
4945 fattrs
= wfd_w
.dwFileAttributes
;
4946 ctime
= wfd_w
.ftCreationTime
;
4947 atime
= wfd_w
.ftLastAccessTime
;
4948 wtime
= wfd_w
.ftLastWriteTime
;
4949 fs_high
= wfd_w
.nFileSizeHigh
;
4950 fs_low
= wfd_w
.nFileSizeLow
;
4954 fattrs
= wfd_a
.dwFileAttributes
;
4955 ctime
= wfd_a
.ftCreationTime
;
4956 atime
= wfd_a
.ftLastAccessTime
;
4957 wtime
= wfd_a
.ftLastWriteTime
;
4958 fs_high
= wfd_a
.nFileSizeHigh
;
4959 fs_low
= wfd_a
.nFileSizeLow
;
4963 serialnum
= volume_info
.serialnum
;
4965 if (is_a_symlink
&& !follow_symlinks
)
4966 buf
->st_mode
= S_IFLNK
;
4967 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4968 buf
->st_mode
= S_IFDIR
;
4970 buf
->st_mode
= S_IFREG
;
4972 get_file_owner_and_group (NULL
, buf
);
4975 buf
->st_ino
= fake_inode
;
4977 buf
->st_dev
= serialnum
;
4978 buf
->st_rdev
= serialnum
;
4980 buf
->st_size
= fs_high
;
4981 buf
->st_size
<<= 32;
4982 buf
->st_size
+= fs_low
;
4983 buf
->st_nlink
= nlinks
;
4985 /* Convert timestamps to Unix format. */
4986 buf
->st_mtime
= convert_time (wtime
);
4987 buf
->st_atime
= convert_time (atime
);
4988 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4989 buf
->st_ctime
= convert_time (ctime
);
4990 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4992 /* determine rwx permissions */
4993 if (is_a_symlink
&& !follow_symlinks
)
4994 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
4997 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
4998 permission
= S_IREAD
;
5000 permission
= S_IREAD
| S_IWRITE
;
5002 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5003 permission
|= S_IEXEC
;
5004 else if (is_exec (name
))
5005 permission
|= S_IEXEC
;
5008 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5014 stat (const char * path
, struct stat
* buf
)
5016 return stat_worker (path
, buf
, 1);
5020 lstat (const char * path
, struct stat
* buf
)
5022 return stat_worker (path
, buf
, 0);
5026 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5028 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5029 This is good enough for the current usage in Emacs, but is fragile.
5031 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5032 Gnulib does this and can serve as a model. */
5033 char fullname
[MAX_UTF8_PATH
];
5037 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5040 errno
= ENAMETOOLONG
;
5046 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5049 /* Provide fstat and utime as well as stat for consistent handling of
5052 fstat (int desc
, struct stat
* buf
)
5054 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5055 BY_HANDLE_FILE_INFORMATION info
;
5056 unsigned __int64 fake_inode
;
5059 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5061 case FILE_TYPE_DISK
:
5062 buf
->st_mode
= S_IFREG
;
5063 if (!GetFileInformationByHandle (fh
, &info
))
5069 case FILE_TYPE_PIPE
:
5070 buf
->st_mode
= S_IFIFO
;
5072 case FILE_TYPE_CHAR
:
5073 case FILE_TYPE_UNKNOWN
:
5075 buf
->st_mode
= S_IFCHR
;
5077 memset (&info
, 0, sizeof (info
));
5078 info
.dwFileAttributes
= 0;
5079 info
.ftCreationTime
= utc_base_ft
;
5080 info
.ftLastAccessTime
= utc_base_ft
;
5081 info
.ftLastWriteTime
= utc_base_ft
;
5084 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5085 buf
->st_mode
= S_IFDIR
;
5087 buf
->st_nlink
= info
.nNumberOfLinks
;
5088 /* Might as well use file index to fake inode values, but this
5089 is not guaranteed to be unique unless we keep a handle open
5090 all the time (even then there are situations where it is
5091 not unique). Reputedly, there are at most 48 bits of info
5092 (on NTFS, presumably less on FAT). */
5093 fake_inode
= info
.nFileIndexHigh
;
5095 fake_inode
+= info
.nFileIndexLow
;
5097 /* MSVC defines _ino_t to be short; other libc's might not. */
5098 if (sizeof (buf
->st_ino
) == 2)
5099 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5101 buf
->st_ino
= fake_inode
;
5103 /* If the caller so requested, get the true file owner and group.
5104 Otherwise, consider the file to belong to the current user. */
5105 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5106 get_file_owner_and_group (NULL
, buf
);
5109 PSECURITY_DESCRIPTOR psd
= NULL
;
5111 psd
= get_file_security_desc_by_handle (fh
);
5114 get_file_owner_and_group (psd
, buf
);
5118 get_file_owner_and_group (NULL
, buf
);
5121 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5122 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5124 buf
->st_size
= info
.nFileSizeHigh
;
5125 buf
->st_size
<<= 32;
5126 buf
->st_size
+= info
.nFileSizeLow
;
5128 /* Convert timestamps to Unix format. */
5129 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5130 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5131 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5132 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5133 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5135 /* determine rwx permissions */
5136 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5137 permission
= S_IREAD
;
5139 permission
= S_IREAD
| S_IWRITE
;
5141 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5142 permission
|= S_IEXEC
;
5145 #if 0 /* no way of knowing the filename */
5146 char * p
= strrchr (name
, '.');
5148 (xstrcasecmp (p
, ".exe") == 0 ||
5149 xstrcasecmp (p
, ".com") == 0 ||
5150 xstrcasecmp (p
, ".bat") == 0 ||
5151 xstrcasecmp (p
, ".cmd") == 0))
5152 permission
|= S_IEXEC
;
5156 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5161 /* A version of 'utime' which handles directories as well as
5165 utime (const char *name
, struct utimbuf
*times
)
5167 struct utimbuf deftime
;
5174 deftime
.modtime
= deftime
.actime
= time (NULL
);
5178 if (w32_unicode_filenames
)
5180 wchar_t name_utf16
[MAX_PATH
];
5182 if (filename_to_utf16 (name
, name_utf16
) != 0)
5183 return -1; /* errno set by filename_to_utf16 */
5185 /* Need write access to set times. */
5186 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5187 /* If NAME specifies a directory, FILE_SHARE_DELETE
5188 allows other processes to delete files inside it,
5189 while we have the directory open. */
5190 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5191 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5195 char name_ansi
[MAX_PATH
];
5197 if (filename_to_ansi (name
, name_ansi
) != 0)
5198 return -1; /* errno set by filename_to_ansi */
5200 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5201 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5202 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5204 if (fh
!= INVALID_HANDLE_VALUE
)
5206 convert_from_time_t (times
->actime
, &atime
);
5207 convert_from_time_t (times
->modtime
, &mtime
);
5208 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5218 DWORD err
= GetLastError ();
5222 case ERROR_FILE_NOT_FOUND
:
5223 case ERROR_PATH_NOT_FOUND
:
5224 case ERROR_INVALID_DRIVE
:
5225 case ERROR_BAD_NETPATH
:
5226 case ERROR_DEV_NOT_EXIST
:
5227 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5228 file name includes ?s, i.e. translation to ANSI failed. */
5229 case ERROR_INVALID_NAME
:
5232 case ERROR_TOO_MANY_OPEN_FILES
:
5235 case ERROR_ACCESS_DENIED
:
5236 case ERROR_SHARING_VIOLATION
:
5249 /* Symlink-related functions. */
5250 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5251 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5255 symlink (char const *filename
, char const *linkname
)
5257 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5259 int dir_access
, filename_ends_in_slash
;
5261 /* Diagnostics follows Posix as much as possible. */
5262 if (filename
== NULL
|| linkname
== NULL
)
5272 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5274 errno
= ENAMETOOLONG
;
5278 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5279 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5285 /* Note: since empty FILENAME was already rejected, we can safely
5286 refer to FILENAME[1]. */
5287 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5289 /* Non-absolute FILENAME is understood as being relative to
5290 LINKNAME's directory. We need to prepend that directory to
5291 FILENAME to get correct results from faccessat below, since
5292 otherwise it will interpret FILENAME relative to the
5293 directory where the Emacs process runs. Note that
5294 make-symbolic-link always makes sure LINKNAME is a fully
5295 expanded file name. */
5296 char tem
[MAX_UTF8_PATH
];
5297 char *p
= linkfn
+ strlen (linkfn
);
5299 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5302 strncpy (tem
, linkfn
, p
- linkfn
);
5303 tem
[p
- linkfn
] = '\0';
5304 strcat (tem
, filename
);
5305 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5308 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5310 /* Since Windows distinguishes between symlinks to directories and
5311 to files, we provide a kludgy feature: if FILENAME doesn't
5312 exist, but ends in a slash, we create a symlink to directory. If
5313 FILENAME exists and is a directory, we always create a symlink to
5315 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5316 if (dir_access
== 0 || filename_ends_in_slash
)
5317 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5319 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5320 if (filename_ends_in_slash
)
5321 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5324 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5326 /* ENOSYS is set by create_symbolic_link, when it detects that
5327 the OS doesn't support the CreateSymbolicLink API. */
5328 if (errno
!= ENOSYS
)
5330 DWORD w32err
= GetLastError ();
5334 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5335 TGTFN point to the same file name, go figure. */
5337 case ERROR_FILE_EXISTS
:
5340 case ERROR_ACCESS_DENIED
:
5343 case ERROR_FILE_NOT_FOUND
:
5344 case ERROR_PATH_NOT_FOUND
:
5345 case ERROR_BAD_NETPATH
:
5346 case ERROR_INVALID_REPARSE_DATA
:
5349 case ERROR_DIRECTORY
:
5352 case ERROR_PRIVILEGE_NOT_HELD
:
5353 case ERROR_NOT_ALL_ASSIGNED
:
5356 case ERROR_DISK_FULL
:
5369 /* A quick inexpensive test of whether FILENAME identifies a file that
5370 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5371 must already be in the normalized form returned by
5374 Note: for repeated operations on many files, it is best to test
5375 whether the underlying volume actually supports symlinks, by
5376 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5377 avoid the call to this function if it doesn't. That's because the
5378 call to GetFileAttributes takes a non-negligible time, especially
5379 on non-local or removable filesystems. See stat_worker for an
5380 example of how to do that. */
5382 is_symlink (const char *filename
)
5385 wchar_t filename_w
[MAX_PATH
];
5386 char filename_a
[MAX_PATH
];
5387 WIN32_FIND_DATAW wfdw
;
5388 WIN32_FIND_DATAA wfda
;
5390 int attrs_mean_symlink
;
5392 if (w32_unicode_filenames
)
5394 filename_to_utf16 (filename
, filename_w
);
5395 attrs
= GetFileAttributesW (filename_w
);
5399 filename_to_ansi (filename
, filename_a
);
5400 attrs
= GetFileAttributesA (filename_a
);
5404 DWORD w32err
= GetLastError ();
5408 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5410 case ERROR_ACCESS_DENIED
:
5413 case ERROR_FILE_NOT_FOUND
:
5414 case ERROR_PATH_NOT_FOUND
:
5421 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5423 logon_network_drive (filename
);
5424 if (w32_unicode_filenames
)
5426 fh
= FindFirstFileW (filename_w
, &wfdw
);
5427 attrs_mean_symlink
=
5428 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5429 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5431 else if (_mbspbrk (filename_a
, "?"))
5433 /* filename_to_ansi failed to convert the file name. */
5439 fh
= FindFirstFileA (filename_a
, &wfda
);
5440 attrs_mean_symlink
=
5441 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5442 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5444 if (fh
== INVALID_HANDLE_VALUE
)
5447 return attrs_mean_symlink
;
5450 /* If NAME identifies a symbolic link, copy into BUF the file name of
5451 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5452 null-terminate the target name, even if it fits. Return the number
5453 of bytes copied, or -1 if NAME is not a symlink or any error was
5454 encountered while resolving it. The file name copied into BUF is
5455 encoded in the current ANSI codepage. */
5457 readlink (const char *name
, char *buf
, size_t buf_size
)
5460 TOKEN_PRIVILEGES privs
;
5461 int restore_privs
= 0;
5464 char resolved
[MAX_UTF8_PATH
];
5477 path
= map_w32_filename (name
, NULL
);
5479 if (strlen (path
) > MAX_UTF8_PATH
)
5481 errno
= ENAMETOOLONG
;
5486 if (is_windows_9x () == TRUE
5487 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5488 || !is_symlink (path
))
5491 errno
= EINVAL
; /* not a symlink */
5495 /* Done with simple tests, now we're in for some _real_ work. */
5496 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5498 /* Implementation note: From here and onward, don't return early,
5499 since that will fail to restore the original set of privileges of
5500 the calling thread. */
5502 retval
= -1; /* not too optimistic, are we? */
5504 /* Note: In the next call to CreateFile, we use zero as the 2nd
5505 argument because, when the symlink is a hidden/system file,
5506 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5507 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5508 and directory symlinks. */
5509 if (w32_unicode_filenames
)
5511 wchar_t path_w
[MAX_PATH
];
5513 filename_to_utf16 (path
, path_w
);
5514 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5515 FILE_FLAG_OPEN_REPARSE_POINT
5516 | FILE_FLAG_BACKUP_SEMANTICS
,
5521 char path_a
[MAX_PATH
];
5523 filename_to_ansi (path
, path_a
);
5524 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5525 FILE_FLAG_OPEN_REPARSE_POINT
5526 | FILE_FLAG_BACKUP_SEMANTICS
,
5529 if (sh
!= INVALID_HANDLE_VALUE
)
5531 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5532 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5535 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5536 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5539 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5543 /* Copy the link target name, in wide characters, from
5544 reparse_data, then convert it to multibyte encoding in
5545 the current locale's codepage. */
5549 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5551 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5552 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5553 size_t size_to_copy
= buf_size
;
5555 /* According to MSDN, PrintNameLength does not include the
5556 terminating null character. */
5557 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5558 memcpy (lwname
, lwname_src
, lwname_len
);
5559 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5560 filename_from_utf16 (lwname
, resolved
);
5561 dostounix_filename (resolved
);
5562 lname_size
= strlen (resolved
) + 1;
5563 if (lname_size
<= buf_size
)
5564 size_to_copy
= lname_size
;
5565 strncpy (buf
, resolved
, size_to_copy
);
5567 retval
= size_to_copy
;
5573 /* CreateFile failed. */
5574 DWORD w32err2
= GetLastError ();
5578 case ERROR_FILE_NOT_FOUND
:
5579 case ERROR_PATH_NOT_FOUND
:
5582 case ERROR_ACCESS_DENIED
:
5583 case ERROR_TOO_MANY_OPEN_FILES
:
5593 restore_privilege (&privs
);
5601 readlinkat (int fd
, char const *name
, char *buffer
,
5604 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5605 as in fstatat. FIXME: Add proper support for readlinkat. */
5606 char fullname
[MAX_UTF8_PATH
];
5610 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5613 errno
= ENAMETOOLONG
;
5619 return readlink (name
, buffer
, buffer_size
);
5622 /* If FILE is a symlink, return its target (stored in a static
5623 buffer); otherwise return FILE.
5625 This function repeatedly resolves symlinks in the last component of
5626 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5627 until it arrives at a file whose last component is not a symlink,
5628 or some error occurs. It returns the target of the last
5629 successfully resolved symlink in the chain. If it succeeds to
5630 resolve even a single symlink, the value returned is an absolute
5631 file name with backslashes (result of GetFullPathName). By
5632 contrast, if the original FILE is returned, it is unaltered.
5634 Note: This function can set errno even if it succeeds.
5636 Implementation note: we only resolve the last portion ("basename")
5637 of the argument FILE and of each following file in the chain,
5638 disregarding any possible symlinks in its leading directories.
5639 This is because Windows system calls and library functions
5640 transparently resolve symlinks in leading directories and return
5641 correct information, as long as the basename is not a symlink. */
5643 chase_symlinks (const char *file
)
5645 static char target
[MAX_UTF8_PATH
];
5646 char link
[MAX_UTF8_PATH
];
5647 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5648 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5649 ssize_t res
, link_len
;
5652 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5653 return (char *)file
;
5655 if (w32_unicode_filenames
)
5657 wchar_t file_w
[MAX_PATH
];
5659 filename_to_utf16 (file
, file_w
);
5660 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5661 return (char *)file
;
5662 filename_from_utf16 (link_w
, link
);
5666 char file_a
[MAX_PATH
];
5668 filename_to_ansi (file
, file_a
);
5669 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5670 return (char *)file
;
5671 filename_from_ansi (link_a
, link
);
5673 link_len
= strlen (link
);
5678 /* Remove trailing slashes, as we want to resolve the last
5679 non-trivial part of the link name. */
5680 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5681 link
[link_len
--] = '\0';
5683 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5687 if (!(IS_DEVICE_SEP (target
[1])
5688 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5690 /* Target is relative. Append it to the directory part of
5691 the symlink, then copy the result back to target. */
5692 char *p
= link
+ link_len
;
5694 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5697 strcpy (target
, link
);
5699 /* Resolve any "." and ".." to get a fully-qualified file name
5701 if (w32_unicode_filenames
)
5703 filename_to_utf16 (target
, target_w
);
5704 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5706 filename_from_utf16 (link_w
, link
);
5710 filename_to_ansi (target
, target_a
);
5711 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5713 filename_from_ansi (link_a
, link
);
5715 link_len
= strlen (link
);
5717 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5719 if (loop_count
> 100)
5722 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5723 return (char *)file
;
5728 /* Posix ACL emulation. */
5731 acl_valid (acl_t acl
)
5733 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5737 acl_to_text (acl_t acl
, ssize_t
*size
)
5740 SECURITY_INFORMATION flags
=
5741 OWNER_SECURITY_INFORMATION
|
5742 GROUP_SECURITY_INFORMATION
|
5743 DACL_SECURITY_INFORMATION
;
5744 char *retval
= NULL
;
5750 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5753 /* We don't want to mix heaps, so we duplicate the string in our
5754 heap and free the one allocated by the API. */
5755 retval
= xstrdup (str_acl
);
5758 LocalFree (str_acl
);
5760 else if (errno
!= ENOTSUP
)
5767 acl_from_text (const char *acl_str
)
5769 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5775 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5778 retval
= xmalloc (sd_size
);
5779 memcpy (retval
, psd
, sd_size
);
5782 else if (errno
!= ENOTSUP
)
5789 acl_free (void *ptr
)
5796 acl_get_file (const char *fname
, acl_type_t type
)
5798 PSECURITY_DESCRIPTOR psd
= NULL
;
5799 const char *filename
;
5801 if (type
== ACL_TYPE_ACCESS
)
5804 SECURITY_INFORMATION si
=
5805 OWNER_SECURITY_INFORMATION
|
5806 GROUP_SECURITY_INFORMATION
|
5807 DACL_SECURITY_INFORMATION
;
5810 filename
= map_w32_filename (fname
, NULL
);
5811 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5812 fname
= chase_symlinks (filename
);
5817 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5818 && errno
!= ENOTSUP
)
5820 err
= GetLastError ();
5821 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5823 psd
= xmalloc (sd_len
);
5824 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5831 else if (err
== ERROR_FILE_NOT_FOUND
5832 || err
== ERROR_PATH_NOT_FOUND
5833 /* ERROR_INVALID_NAME is what we get if
5834 w32-unicode-filenames is nil and the file cannot
5835 be encoded in the current ANSI codepage. */
5836 || err
== ERROR_INVALID_NAME
)
5844 else if (type
!= ACL_TYPE_DEFAULT
)
5851 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5853 TOKEN_PRIVILEGES old1
, old2
;
5855 int st
= 0, retval
= -1;
5856 SECURITY_INFORMATION flags
= 0;
5862 const char *filename
;
5864 if (acl_valid (acl
) != 0
5865 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5871 if (type
== ACL_TYPE_DEFAULT
)
5877 filename
= map_w32_filename (fname
, NULL
);
5878 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5879 fname
= chase_symlinks (filename
);
5883 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5885 flags
|= OWNER_SECURITY_INFORMATION
;
5886 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5888 flags
|= GROUP_SECURITY_INFORMATION
;
5889 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5892 flags
|= DACL_SECURITY_INFORMATION
;
5896 /* According to KB-245153, setting the owner will succeed if either:
5897 (1) the caller is the user who will be the new owner, and has the
5898 SE_TAKE_OWNERSHIP privilege, or
5899 (2) the caller has the SE_RESTORE privilege, in which case she can
5900 set any valid user or group as the owner
5902 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5903 privileges, and disregard any failures in obtaining them. If
5904 these privileges cannot be obtained, and do not already exist in
5905 the calling thread's security token, this function could fail
5907 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5909 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5914 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5916 err
= GetLastError ();
5918 if (errno
== ENOTSUP
)
5920 else if (err
== ERROR_INVALID_OWNER
5921 || err
== ERROR_NOT_ALL_ASSIGNED
5922 || err
== ERROR_ACCESS_DENIED
)
5924 /* Maybe the requested ACL and the one the file already has
5925 are identical, in which case we can silently ignore the
5926 failure. (And no, Windows doesn't.) */
5927 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5932 char *acl_from
= acl_to_text (current_acl
, NULL
);
5933 char *acl_to
= acl_to_text (acl
, NULL
);
5935 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5941 acl_free (acl_from
);
5944 acl_free (current_acl
);
5947 else if (err
== ERROR_FILE_NOT_FOUND
5948 || err
== ERROR_PATH_NOT_FOUND
5949 /* ERROR_INVALID_NAME is what we get if
5950 w32-unicode-filenames is nil and the file cannot be
5951 encoded in the current ANSI codepage. */
5952 || err
== ERROR_INVALID_NAME
)
5966 restore_privilege (&old2
);
5967 restore_privilege (&old1
);
5975 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5976 have a fixed max size for file names, so we don't need the kind of
5977 alloc/malloc/realloc dance the gnulib version does. We also don't
5978 support FD-relative symlinks. */
5980 careadlinkat (int fd
, char const *filename
,
5981 char *buffer
, size_t buffer_size
,
5982 struct allocator
const *alloc
,
5983 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
5985 char linkname
[MAX_UTF8_PATH
];
5988 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
5992 char *retval
= buffer
;
5994 linkname
[link_size
++] = '\0';
5995 if (link_size
> buffer_size
)
5996 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
5998 memcpy (retval
, linkname
, link_size
);
6006 w32_copy_file (const char *from
, const char *to
,
6007 int keep_time
, int preserve_ownership
, int copy_acls
)
6011 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6012 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6014 /* We ignore preserve_ownership for now. */
6015 preserve_ownership
= preserve_ownership
;
6019 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6020 if (acl
== NULL
&& acl_errno_valid (errno
))
6023 if (w32_unicode_filenames
)
6025 filename_to_utf16 (from
, from_w
);
6026 filename_to_utf16 (to
, to_w
);
6027 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6031 filename_to_ansi (from
, from_a
);
6032 filename_to_ansi (to
, to_a
);
6033 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6037 /* CopyFile doesn't set errno when it fails. By far the most
6038 "popular" reason is that the target is read-only. */
6039 DWORD err
= GetLastError ();
6043 case ERROR_FILE_NOT_FOUND
:
6046 case ERROR_ACCESS_DENIED
:
6049 case ERROR_ENCRYPTION_FAILED
:
6061 /* CopyFile retains the timestamp by default. However, see
6062 "Community Additions" for CopyFile: it sounds like that is not
6063 entirely true. Testing on Windows XP confirms that modified time
6064 is copied, but creation and last-access times are not.
6066 else if (!keep_time
)
6068 struct timespec now
;
6071 if (w32_unicode_filenames
)
6073 /* Ensure file is writable while its times are set. */
6074 attributes
= GetFileAttributesW (to_w
);
6075 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6076 now
= current_timespec ();
6077 if (set_file_times (-1, to
, now
, now
))
6079 /* Restore original attributes. */
6080 SetFileAttributesW (to_w
, attributes
);
6085 /* Restore original attributes. */
6086 SetFileAttributesW (to_w
, attributes
);
6090 attributes
= GetFileAttributesA (to_a
);
6091 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6092 now
= current_timespec ();
6093 if (set_file_times (-1, to
, now
, now
))
6095 SetFileAttributesA (to_a
, attributes
);
6100 SetFileAttributesA (to_a
, attributes
);
6106 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6108 if (fail
&& acl_errno_valid (errno
))
6116 /* Support for browsing other processes and their attributes. See
6117 process.c for the Lisp bindings. */
6119 /* Helper wrapper functions. */
6121 static HANDLE WINAPI
6122 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6124 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6126 if (g_b_init_create_toolhelp32_snapshot
== 0)
6128 g_b_init_create_toolhelp32_snapshot
= 1;
6129 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6130 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6131 "CreateToolhelp32Snapshot");
6133 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6135 return INVALID_HANDLE_VALUE
;
6137 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6141 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6143 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6145 if (g_b_init_process32_first
== 0)
6147 g_b_init_process32_first
= 1;
6148 s_pfn_Process32_First
= (Process32First_Proc
)
6149 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6152 if (s_pfn_Process32_First
== NULL
)
6156 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6160 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6162 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6164 if (g_b_init_process32_next
== 0)
6166 g_b_init_process32_next
= 1;
6167 s_pfn_Process32_Next
= (Process32Next_Proc
)
6168 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6171 if (s_pfn_Process32_Next
== NULL
)
6175 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6179 open_thread_token (HANDLE ThreadHandle
,
6180 DWORD DesiredAccess
,
6182 PHANDLE TokenHandle
)
6184 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6185 HMODULE hm_advapi32
= NULL
;
6186 if (is_windows_9x () == TRUE
)
6188 SetLastError (ERROR_NOT_SUPPORTED
);
6191 if (g_b_init_open_thread_token
== 0)
6193 g_b_init_open_thread_token
= 1;
6194 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6195 s_pfn_Open_Thread_Token
=
6196 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6198 if (s_pfn_Open_Thread_Token
== NULL
)
6200 SetLastError (ERROR_NOT_SUPPORTED
);
6204 s_pfn_Open_Thread_Token (
6213 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6215 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6216 HMODULE hm_advapi32
= NULL
;
6217 if (is_windows_9x () == TRUE
)
6221 if (g_b_init_impersonate_self
== 0)
6223 g_b_init_impersonate_self
= 1;
6224 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6225 s_pfn_Impersonate_Self
=
6226 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6228 if (s_pfn_Impersonate_Self
== NULL
)
6232 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6236 revert_to_self (void)
6238 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6239 HMODULE hm_advapi32
= NULL
;
6240 if (is_windows_9x () == TRUE
)
6244 if (g_b_init_revert_to_self
== 0)
6246 g_b_init_revert_to_self
= 1;
6247 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6248 s_pfn_Revert_To_Self
=
6249 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6251 if (s_pfn_Revert_To_Self
== NULL
)
6255 return s_pfn_Revert_To_Self ();
6259 get_process_memory_info (HANDLE h_proc
,
6260 PPROCESS_MEMORY_COUNTERS mem_counters
,
6263 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6264 HMODULE hm_psapi
= NULL
;
6265 if (is_windows_9x () == TRUE
)
6269 if (g_b_init_get_process_memory_info
== 0)
6271 g_b_init_get_process_memory_info
= 1;
6272 hm_psapi
= LoadLibrary ("Psapi.dll");
6274 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6275 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6277 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6281 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6285 get_process_working_set_size (HANDLE h_proc
,
6289 static GetProcessWorkingSetSize_Proc
6290 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6292 if (is_windows_9x () == TRUE
)
6296 if (g_b_init_get_process_working_set_size
== 0)
6298 g_b_init_get_process_working_set_size
= 1;
6299 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6300 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6301 "GetProcessWorkingSetSize");
6303 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6307 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6311 global_memory_status (MEMORYSTATUS
*buf
)
6313 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6315 if (is_windows_9x () == TRUE
)
6319 if (g_b_init_global_memory_status
== 0)
6321 g_b_init_global_memory_status
= 1;
6322 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6323 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6324 "GlobalMemoryStatus");
6326 if (s_pfn_Global_Memory_Status
== NULL
)
6330 return s_pfn_Global_Memory_Status (buf
);
6334 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6336 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6338 if (is_windows_9x () == TRUE
)
6342 if (g_b_init_global_memory_status_ex
== 0)
6344 g_b_init_global_memory_status_ex
= 1;
6345 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6346 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6347 "GlobalMemoryStatusEx");
6349 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6353 return s_pfn_Global_Memory_Status_Ex (buf
);
6357 list_system_processes (void)
6359 struct gcpro gcpro1
;
6360 Lisp_Object proclist
= Qnil
;
6363 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6365 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6367 PROCESSENTRY32 proc_entry
;
6373 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6374 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6375 res
= process32_next (h_snapshot
, &proc_entry
))
6377 proc_id
= proc_entry
.th32ProcessID
;
6378 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6381 CloseHandle (h_snapshot
);
6383 proclist
= Fnreverse (proclist
);
6390 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6392 TOKEN_PRIVILEGES priv
;
6393 DWORD priv_size
= sizeof (priv
);
6394 DWORD opriv_size
= sizeof (*old_priv
);
6395 HANDLE h_token
= NULL
;
6396 HANDLE h_thread
= GetCurrentThread ();
6400 res
= open_thread_token (h_thread
,
6401 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6403 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6405 if (impersonate_self (SecurityImpersonation
))
6406 res
= open_thread_token (h_thread
,
6407 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6412 priv
.PrivilegeCount
= 1;
6413 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6414 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6415 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6416 old_priv
, &opriv_size
)
6417 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6421 CloseHandle (h_token
);
6427 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6429 DWORD priv_size
= sizeof (*priv
);
6430 HANDLE h_token
= NULL
;
6433 if (open_thread_token (GetCurrentThread (),
6434 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6437 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6438 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6442 CloseHandle (h_token
);
6448 ltime (ULONGLONG time_100ns
)
6450 ULONGLONG time_sec
= time_100ns
/ 10000000;
6451 int subsec
= time_100ns
% 10000000;
6452 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6453 subsec
/ 10, subsec
% 10 * 100000);
6456 #define U64_TO_LISP_TIME(time) ltime (time)
6459 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6460 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6463 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6464 ULONGLONG tem1
, tem2
, tem3
, tem
;
6467 || !get_process_times_fn
6468 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6469 &ft_kernel
, &ft_user
))
6472 GetSystemTimeAsFileTime (&ft_current
);
6474 FILETIME_TO_U64 (tem1
, ft_kernel
);
6475 *stime
= U64_TO_LISP_TIME (tem1
);
6477 FILETIME_TO_U64 (tem2
, ft_user
);
6478 *utime
= U64_TO_LISP_TIME (tem2
);
6481 *ttime
= U64_TO_LISP_TIME (tem3
);
6483 FILETIME_TO_U64 (tem
, ft_creation
);
6484 /* Process no 4 (System) returns zero creation time. */
6487 *ctime
= U64_TO_LISP_TIME (tem
);
6491 FILETIME_TO_U64 (tem3
, ft_current
);
6492 tem
= (tem3
- utc_base
) - tem
;
6494 *etime
= U64_TO_LISP_TIME (tem
);
6498 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6509 system_process_attributes (Lisp_Object pid
)
6511 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6512 Lisp_Object attrs
= Qnil
;
6513 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6514 HANDLE h_snapshot
, h_proc
;
6517 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6518 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6519 DWORD glength
= sizeof (gname
);
6520 HANDLE token
= NULL
;
6521 SID_NAME_USE user_type
;
6522 unsigned char *buf
= NULL
;
6524 TOKEN_USER user_token
;
6525 TOKEN_PRIMARY_GROUP group_token
;
6528 PROCESS_MEMORY_COUNTERS mem
;
6529 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6530 SIZE_T minrss
, maxrss
;
6532 MEMORY_STATUS_EX memstex
;
6533 double totphys
= 0.0;
6534 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6536 BOOL result
= FALSE
;
6538 CHECK_NUMBER_OR_FLOAT (pid
);
6539 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6541 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6543 GCPRO3 (attrs
, decoded_cmd
, tem
);
6545 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6550 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6551 for (res
= process32_first (h_snapshot
, &pe
); res
;
6552 res
= process32_next (h_snapshot
, &pe
))
6554 if (proc_id
== pe
.th32ProcessID
)
6557 decoded_cmd
= build_string ("Idle");
6560 /* Decode the command name from locale-specific
6562 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6565 code_convert_string_norecord (cmd_str
,
6566 Vlocale_coding_system
, 0);
6568 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6569 attrs
= Fcons (Fcons (Qppid
,
6570 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6572 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6574 attrs
= Fcons (Fcons (Qthcount
,
6575 make_fixnum_or_float (pe
.cntThreads
)),
6582 CloseHandle (h_snapshot
);
6591 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6593 /* If we were denied a handle to the process, try again after
6594 enabling the SeDebugPrivilege in our process. */
6597 TOKEN_PRIVILEGES priv_current
;
6599 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6601 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6603 restore_privilege (&priv_current
);
6609 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6612 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6613 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6615 buf
= xmalloc (blen
);
6616 result
= get_token_information (token
, TokenUser
,
6617 (LPVOID
)buf
, blen
, &needed
);
6620 memcpy (&user_token
, buf
, sizeof (user_token
));
6621 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6623 euid
= get_rid (user_token
.User
.Sid
);
6624 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6629 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6632 strcpy (uname
, "unknown");
6636 ulength
= strlen (uname
);
6642 /* Determine a reasonable euid and gid values. */
6643 if (xstrcasecmp ("administrator", uname
) == 0)
6645 euid
= 500; /* well-known Administrator uid */
6646 egid
= 513; /* well-known None gid */
6650 /* Get group id and name. */
6651 result
= get_token_information (token
, TokenPrimaryGroup
,
6652 (LPVOID
)buf
, blen
, &needed
);
6653 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6655 buf
= xrealloc (buf
, blen
= needed
);
6656 result
= get_token_information (token
, TokenPrimaryGroup
,
6657 (LPVOID
)buf
, blen
, &needed
);
6661 memcpy (&group_token
, buf
, sizeof (group_token
));
6662 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6664 egid
= get_rid (group_token
.PrimaryGroup
);
6665 dlength
= sizeof (domain
);
6667 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6668 gname
, &glength
, NULL
, &dlength
,
6671 w32_add_to_cache (group_token
.PrimaryGroup
,
6675 strcpy (gname
, "None");
6679 glength
= strlen (gname
);
6687 if (!is_windows_9x ())
6689 /* We couldn't open the process token, presumably because of
6690 insufficient access rights. Assume this process is run
6692 strcpy (uname
, "SYSTEM");
6693 strcpy (gname
, "None");
6694 euid
= 18; /* SYSTEM */
6695 egid
= 513; /* None */
6696 glength
= strlen (gname
);
6697 ulength
= strlen (uname
);
6699 /* If we are running under Windows 9X, where security calls are
6700 not supported, we assume all processes are run by the current
6702 else if (GetUserName (uname
, &ulength
))
6704 if (xstrcasecmp ("administrator", uname
) == 0)
6709 strcpy (gname
, "None");
6710 glength
= strlen (gname
);
6711 ulength
= strlen (uname
);
6717 strcpy (uname
, "administrator");
6718 ulength
= strlen (uname
);
6719 strcpy (gname
, "None");
6720 glength
= strlen (gname
);
6723 CloseHandle (token
);
6726 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6727 tem
= make_unibyte_string (uname
, ulength
);
6728 attrs
= Fcons (Fcons (Quser
,
6729 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6731 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6732 tem
= make_unibyte_string (gname
, glength
);
6733 attrs
= Fcons (Fcons (Qgroup
,
6734 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6737 if (global_memory_status_ex (&memstex
))
6738 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6739 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6741 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6742 double, so we need to do this for it... */
6744 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6745 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6746 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6748 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6750 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6751 else if (global_memory_status (&memst
))
6752 totphys
= memst
.dwTotalPhys
/ 1024.0;
6755 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6758 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6760 attrs
= Fcons (Fcons (Qmajflt
,
6761 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6763 attrs
= Fcons (Fcons (Qvsize
,
6764 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6766 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6768 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6771 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6773 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6775 attrs
= Fcons (Fcons (Qmajflt
,
6776 make_fixnum_or_float (mem
.PageFaultCount
)),
6778 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6780 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6783 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6785 DWORD rss
= maxrss
/ 1024;
6787 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6789 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6792 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6794 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6795 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6796 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6797 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6798 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6799 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6802 /* FIXME: Retrieve command line by walking the PEB of the process. */
6805 CloseHandle (h_proc
);
6811 /* Wrappers for winsock functions to map between our file descriptors
6812 and winsock's handles; also set h_errno for convenience.
6814 To allow Emacs to run on systems which don't have winsock support
6815 installed, we dynamically link to winsock on startup if present, and
6816 otherwise provide the minimum necessary functionality
6817 (eg. gethostname). */
6819 /* function pointers for relevant socket functions */
6820 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6821 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6822 int (PASCAL
*pfn_WSAGetLastError
) (void);
6823 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6824 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6825 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6826 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6827 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6828 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6829 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6830 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6831 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6832 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6833 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6834 int (PASCAL
*pfn_WSACleanup
) (void);
6836 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6837 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6838 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6839 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6840 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6841 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6842 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6843 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6844 const char * optval
, int optlen
);
6845 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6846 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6848 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6849 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6850 struct sockaddr
* from
, int * fromlen
);
6851 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6852 const struct sockaddr
* to
, int tolen
);
6854 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6855 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6856 #ifndef HANDLE_FLAG_INHERIT
6857 #define HANDLE_FLAG_INHERIT 1
6861 static int winsock_inuse
;
6866 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6868 release_listen_threads ();
6869 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6870 after WSAStartup returns successfully, but it seems reasonable
6871 to allow unloading winsock anyway in that case. */
6872 if (pfn_WSACleanup () == 0 ||
6873 pfn_WSAGetLastError () == WSAENETDOWN
)
6875 if (FreeLibrary (winsock_lib
))
6884 init_winsock (int load_now
)
6886 WSADATA winsockData
;
6888 if (winsock_lib
!= NULL
)
6891 pfn_SetHandleInformation
6892 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6893 "SetHandleInformation");
6895 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6897 if (winsock_lib
!= NULL
)
6899 /* dynamically link to socket functions */
6901 #define LOAD_PROC(fn) \
6902 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6905 LOAD_PROC (WSAStartup
);
6906 LOAD_PROC (WSASetLastError
);
6907 LOAD_PROC (WSAGetLastError
);
6908 LOAD_PROC (WSAEventSelect
);
6909 LOAD_PROC (WSACreateEvent
);
6910 LOAD_PROC (WSACloseEvent
);
6913 LOAD_PROC (connect
);
6914 LOAD_PROC (ioctlsocket
);
6917 LOAD_PROC (closesocket
);
6918 LOAD_PROC (shutdown
);
6921 LOAD_PROC (inet_addr
);
6922 LOAD_PROC (gethostname
);
6923 LOAD_PROC (gethostbyname
);
6924 LOAD_PROC (getservbyname
);
6925 LOAD_PROC (getpeername
);
6926 LOAD_PROC (WSACleanup
);
6927 LOAD_PROC (setsockopt
);
6929 LOAD_PROC (getsockname
);
6931 LOAD_PROC (recvfrom
);
6935 /* specify version 1.1 of winsock */
6936 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6938 if (winsockData
.wVersion
!= 0x101)
6943 /* Report that winsock exists and is usable, but leave
6944 socket functions disabled. I am assuming that calling
6945 WSAStartup does not require any network interaction,
6946 and in particular does not cause or require a dial-up
6947 connection to be established. */
6950 FreeLibrary (winsock_lib
);
6958 FreeLibrary (winsock_lib
);
6968 /* Function to map winsock error codes to errno codes for those errno
6969 code defined in errno.h (errno values not defined by errno.h are
6970 already in nt/inc/sys/socket.h). */
6977 if (winsock_lib
== NULL
)
6980 wsa_err
= pfn_WSAGetLastError ();
6984 case WSAEACCES
: errno
= EACCES
; break;
6985 case WSAEBADF
: errno
= EBADF
; break;
6986 case WSAEFAULT
: errno
= EFAULT
; break;
6987 case WSAEINTR
: errno
= EINTR
; break;
6988 case WSAEINVAL
: errno
= EINVAL
; break;
6989 case WSAEMFILE
: errno
= EMFILE
; break;
6990 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
6991 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
6992 default: errno
= wsa_err
; break;
7000 if (winsock_lib
!= NULL
)
7001 pfn_WSASetLastError (0);
7004 /* Extend strerror to handle the winsock-specific error codes. */
7008 } _wsa_errlist
[] = {
7009 {WSAEINTR
, "Interrupted function call"},
7010 {WSAEBADF
, "Bad file descriptor"},
7011 {WSAEACCES
, "Permission denied"},
7012 {WSAEFAULT
, "Bad address"},
7013 {WSAEINVAL
, "Invalid argument"},
7014 {WSAEMFILE
, "Too many open files"},
7016 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7017 {WSAEINPROGRESS
, "Operation now in progress"},
7018 {WSAEALREADY
, "Operation already in progress"},
7019 {WSAENOTSOCK
, "Socket operation on non-socket"},
7020 {WSAEDESTADDRREQ
, "Destination address required"},
7021 {WSAEMSGSIZE
, "Message too long"},
7022 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7023 {WSAENOPROTOOPT
, "Bad protocol option"},
7024 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7025 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7026 {WSAEOPNOTSUPP
, "Operation not supported"},
7027 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7028 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7029 {WSAEADDRINUSE
, "Address already in use"},
7030 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7031 {WSAENETDOWN
, "Network is down"},
7032 {WSAENETUNREACH
, "Network is unreachable"},
7033 {WSAENETRESET
, "Network dropped connection on reset"},
7034 {WSAECONNABORTED
, "Software caused connection abort"},
7035 {WSAECONNRESET
, "Connection reset by peer"},
7036 {WSAENOBUFS
, "No buffer space available"},
7037 {WSAEISCONN
, "Socket is already connected"},
7038 {WSAENOTCONN
, "Socket is not connected"},
7039 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7040 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7041 {WSAETIMEDOUT
, "Connection timed out"},
7042 {WSAECONNREFUSED
, "Connection refused"},
7043 {WSAELOOP
, "Network loop"}, /* not sure */
7044 {WSAENAMETOOLONG
, "Name is too long"},
7045 {WSAEHOSTDOWN
, "Host is down"},
7046 {WSAEHOSTUNREACH
, "No route to host"},
7047 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7048 {WSAEPROCLIM
, "Too many processes"},
7049 {WSAEUSERS
, "Too many users"}, /* not sure */
7050 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7051 {WSAESTALE
, "Data is stale"}, /* not sure */
7052 {WSAEREMOTE
, "Remote error"}, /* not sure */
7054 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7055 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7056 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7057 {WSAEDISCON
, "Graceful shutdown in progress"},
7059 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7060 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7061 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7062 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7063 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7064 {WSASYSCALLFAILURE
, "System call failure"},
7065 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7066 {WSATYPE_NOT_FOUND
, "Class type not found"},
7067 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7068 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7069 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7072 {WSAHOST_NOT_FOUND
, "Host not found"},
7073 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7074 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7075 {WSANO_DATA
, "Valid name, no data record of requested type"},
7081 sys_strerror (int error_no
)
7084 static char unknown_msg
[40];
7086 if (error_no
>= 0 && error_no
< sys_nerr
)
7087 return sys_errlist
[error_no
];
7089 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7090 if (_wsa_errlist
[i
].errnum
== error_no
)
7091 return _wsa_errlist
[i
].msg
;
7093 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7097 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7098 but I believe the method of keeping the socket handle separate (and
7099 insuring it is not inheritable) is the correct one. */
7101 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7103 static int socket_to_fd (SOCKET s
);
7106 sys_socket (int af
, int type
, int protocol
)
7110 if (winsock_lib
== NULL
)
7113 return INVALID_SOCKET
;
7118 /* call the real socket function */
7119 s
= pfn_socket (af
, type
, protocol
);
7121 if (s
!= INVALID_SOCKET
)
7122 return socket_to_fd (s
);
7128 /* Convert a SOCKET to a file descriptor. */
7130 socket_to_fd (SOCKET s
)
7135 /* Although under NT 3.5 _open_osfhandle will accept a socket
7136 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7137 that does not work under NT 3.1. However, we can get the same
7138 effect by using a backdoor function to replace an existing
7139 descriptor handle with the one we want. */
7141 /* allocate a file descriptor (with appropriate flags) */
7142 fd
= _open ("NUL:", _O_RDWR
);
7145 /* Make a non-inheritable copy of the socket handle. Note
7146 that it is possible that sockets aren't actually kernel
7147 handles, which appears to be the case on Windows 9x when
7148 the MS Proxy winsock client is installed. */
7150 /* Apparently there is a bug in NT 3.51 with some service
7151 packs, which prevents using DuplicateHandle to make a
7152 socket handle non-inheritable (causes WSACleanup to
7153 hang). The work-around is to use SetHandleInformation
7154 instead if it is available and implemented. */
7155 if (pfn_SetHandleInformation
)
7157 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7161 HANDLE parent
= GetCurrentProcess ();
7162 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7164 if (DuplicateHandle (parent
,
7170 DUPLICATE_SAME_ACCESS
))
7172 /* It is possible that DuplicateHandle succeeds even
7173 though the socket wasn't really a kernel handle,
7174 because a real handle has the same value. So
7175 test whether the new handle really is a socket. */
7176 long nonblocking
= 0;
7177 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7179 pfn_closesocket (s
);
7184 CloseHandle (new_s
);
7189 eassert (fd
< MAXDESC
);
7190 fd_info
[fd
].hnd
= (HANDLE
) s
;
7192 /* set our own internal flags */
7193 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7199 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7201 /* attach child_process to fd_info */
7202 if (fd_info
[ fd
].cp
!= NULL
)
7204 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7208 fd_info
[ fd
].cp
= cp
;
7211 winsock_inuse
++; /* count open sockets */
7219 pfn_closesocket (s
);
7225 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7227 if (winsock_lib
== NULL
)
7230 return SOCKET_ERROR
;
7234 if (fd_info
[s
].flags
& FILE_SOCKET
)
7236 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7237 if (rc
== SOCKET_ERROR
)
7242 return SOCKET_ERROR
;
7246 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7248 if (winsock_lib
== NULL
)
7251 return SOCKET_ERROR
;
7255 if (fd_info
[s
].flags
& FILE_SOCKET
)
7257 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7258 if (rc
== SOCKET_ERROR
)
7263 return SOCKET_ERROR
;
7267 sys_htons (u_short hostshort
)
7269 return (winsock_lib
!= NULL
) ?
7270 pfn_htons (hostshort
) : hostshort
;
7274 sys_ntohs (u_short netshort
)
7276 return (winsock_lib
!= NULL
) ?
7277 pfn_ntohs (netshort
) : netshort
;
7281 sys_inet_addr (const char * cp
)
7283 return (winsock_lib
!= NULL
) ?
7284 pfn_inet_addr (cp
) : INADDR_NONE
;
7288 sys_gethostname (char * name
, int namelen
)
7290 if (winsock_lib
!= NULL
)
7295 retval
= pfn_gethostname (name
, namelen
);
7296 if (retval
== SOCKET_ERROR
)
7301 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7302 return !GetComputerName (name
, (DWORD
*)&namelen
);
7305 return SOCKET_ERROR
;
7309 sys_gethostbyname (const char * name
)
7311 struct hostent
* host
;
7312 int h_err
= h_errno
;
7314 if (winsock_lib
== NULL
)
7316 h_errno
= NO_RECOVERY
;
7322 host
= pfn_gethostbyname (name
);
7334 sys_getservbyname (const char * name
, const char * proto
)
7336 struct servent
* serv
;
7338 if (winsock_lib
== NULL
)
7345 serv
= pfn_getservbyname (name
, proto
);
7352 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7354 if (winsock_lib
== NULL
)
7357 return SOCKET_ERROR
;
7361 if (fd_info
[s
].flags
& FILE_SOCKET
)
7363 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7364 if (rc
== SOCKET_ERROR
)
7369 return SOCKET_ERROR
;
7373 sys_shutdown (int s
, int how
)
7375 if (winsock_lib
== NULL
)
7378 return SOCKET_ERROR
;
7382 if (fd_info
[s
].flags
& FILE_SOCKET
)
7384 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7385 if (rc
== SOCKET_ERROR
)
7390 return SOCKET_ERROR
;
7394 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7396 if (winsock_lib
== NULL
)
7399 return SOCKET_ERROR
;
7403 if (fd_info
[s
].flags
& FILE_SOCKET
)
7405 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7406 (const char *)optval
, optlen
);
7407 if (rc
== SOCKET_ERROR
)
7412 return SOCKET_ERROR
;
7416 sys_listen (int s
, int backlog
)
7418 if (winsock_lib
== NULL
)
7421 return SOCKET_ERROR
;
7425 if (fd_info
[s
].flags
& FILE_SOCKET
)
7427 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7428 if (rc
== SOCKET_ERROR
)
7431 fd_info
[s
].flags
|= FILE_LISTEN
;
7435 return SOCKET_ERROR
;
7439 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7441 if (winsock_lib
== NULL
)
7444 return SOCKET_ERROR
;
7448 if (fd_info
[s
].flags
& FILE_SOCKET
)
7450 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7451 if (rc
== SOCKET_ERROR
)
7456 return SOCKET_ERROR
;
7460 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7462 if (winsock_lib
== NULL
)
7469 if (fd_info
[s
].flags
& FILE_LISTEN
)
7471 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7473 if (t
== INVALID_SOCKET
)
7476 fd
= socket_to_fd (t
);
7480 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7481 ResetEvent (fd_info
[s
].cp
->char_avail
);
7490 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7491 struct sockaddr
* from
, int * fromlen
)
7493 if (winsock_lib
== NULL
)
7496 return SOCKET_ERROR
;
7500 if (fd_info
[s
].flags
& FILE_SOCKET
)
7502 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7503 if (rc
== SOCKET_ERROR
)
7508 return SOCKET_ERROR
;
7512 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7513 const struct sockaddr
* to
, int tolen
)
7515 if (winsock_lib
== NULL
)
7518 return SOCKET_ERROR
;
7522 if (fd_info
[s
].flags
& FILE_SOCKET
)
7524 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7525 if (rc
== SOCKET_ERROR
)
7530 return SOCKET_ERROR
;
7533 /* Windows does not have an fcntl function. Provide an implementation
7534 good enough for Emacs. */
7536 fcntl (int s
, int cmd
, int options
)
7538 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7539 invoked in a context where fd1 is closed and all descriptors less
7540 than fd1 are open, so sys_dup is an adequate implementation. */
7541 if (cmd
== F_DUPFD_CLOEXEC
)
7544 if (winsock_lib
== NULL
)
7551 if (fd_info
[s
].flags
& FILE_SOCKET
)
7553 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7555 unsigned long nblock
= 1;
7556 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7557 if (rc
== SOCKET_ERROR
)
7559 /* Keep track of the fact that we set this to non-blocking. */
7560 fd_info
[s
].flags
|= FILE_NDELAY
;
7566 return SOCKET_ERROR
;
7570 return SOCKET_ERROR
;
7574 /* Shadow main io functions: we need to handle pipes and sockets more
7575 intelligently, and implement non-blocking mode as well. */
7588 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7590 child_process
* cp
= fd_info
[fd
].cp
;
7592 fd_info
[fd
].cp
= NULL
;
7594 if (CHILD_ACTIVE (cp
))
7596 /* if last descriptor to active child_process then cleanup */
7598 for (i
= 0; i
< MAXDESC
; i
++)
7602 if (fd_info
[i
].cp
== cp
)
7607 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7609 if (winsock_lib
== NULL
) emacs_abort ();
7611 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7612 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7614 winsock_inuse
--; /* count open sockets */
7616 /* If the process handle is NULL, it's either a socket
7617 or serial connection, or a subprocess that was
7618 already reaped by reap_subprocess, but whose
7619 resources were not yet freed, because its output was
7620 not fully read yet by the time it was reaped. (This
7621 usually happens with async subprocesses whose output
7622 is being read by Emacs.) Otherwise, this process was
7623 not reaped yet, so we set its FD to a negative value
7624 to make sure sys_select will eventually get to
7625 calling the SIGCHLD handler for it, which will then
7626 invoke waitpid and reap_subprocess. */
7627 if (cp
->procinfo
.hProcess
== NULL
)
7635 if (fd
>= 0 && fd
< MAXDESC
)
7636 fd_info
[fd
].flags
= 0;
7638 /* Note that sockets do not need special treatment here (at least on
7639 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7640 closesocket is equivalent to CloseHandle, which is to be expected
7641 because socket handles are fully fledged kernel handles. */
7653 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7655 /* duplicate our internal info as well */
7656 fd_info
[new_fd
] = fd_info
[fd
];
7662 sys_dup2 (int src
, int dst
)
7666 if (dst
< 0 || dst
>= MAXDESC
)
7672 /* make sure we close the destination first if it's a pipe or socket */
7673 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7676 rc
= _dup2 (src
, dst
);
7679 /* duplicate our internal info as well */
7680 fd_info
[dst
] = fd_info
[src
];
7686 pipe2 (int * phandles
, int pipe2_flags
)
7691 eassert (pipe2_flags
== O_CLOEXEC
);
7693 /* make pipe handles non-inheritable; when we spawn a child, we
7694 replace the relevant handle with an inheritable one. Also put
7695 pipes into binary mode; we will do text mode translation ourselves
7697 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7701 /* Protect against overflow, since Windows can open more handles than
7702 our fd_info array has room for. */
7703 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7705 _close (phandles
[0]);
7706 _close (phandles
[1]);
7712 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7713 fd_info
[phandles
[0]].flags
= flags
;
7715 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7716 fd_info
[phandles
[1]].flags
= flags
;
7723 /* Function to do blocking read of one byte, needed to implement
7724 select. It is only allowed on communication ports, sockets, or
7727 _sys_read_ahead (int fd
)
7732 if (fd
< 0 || fd
>= MAXDESC
)
7733 return STATUS_READ_ERROR
;
7735 cp
= fd_info
[fd
].cp
;
7737 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7738 return STATUS_READ_ERROR
;
7740 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7741 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7743 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7747 cp
->status
= STATUS_READ_IN_PROGRESS
;
7749 if (fd_info
[fd
].flags
& FILE_PIPE
)
7751 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7753 /* Give subprocess time to buffer some more output for us before
7754 reporting that input is available; we need this because Windows 95
7755 connects DOS programs to pipes by making the pipe appear to be
7756 the normal console stdout - as a result most DOS programs will
7757 write to stdout without buffering, ie. one character at a
7758 time. Even some W32 programs do this - "dir" in a command
7759 shell on NT is very slow if we don't do this. */
7762 int wait
= w32_pipe_read_delay
;
7768 /* Yield remainder of our time slice, effectively giving a
7769 temporary priority boost to the child process. */
7773 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7775 HANDLE hnd
= fd_info
[fd
].hnd
;
7776 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7779 /* Configure timeouts for blocking read. */
7780 if (!GetCommTimeouts (hnd
, &ct
))
7782 cp
->status
= STATUS_READ_ERROR
;
7783 return STATUS_READ_ERROR
;
7785 ct
.ReadIntervalTimeout
= 0;
7786 ct
.ReadTotalTimeoutMultiplier
= 0;
7787 ct
.ReadTotalTimeoutConstant
= 0;
7788 if (!SetCommTimeouts (hnd
, &ct
))
7790 cp
->status
= STATUS_READ_ERROR
;
7791 return STATUS_READ_ERROR
;
7794 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7796 if (GetLastError () != ERROR_IO_PENDING
)
7798 cp
->status
= STATUS_READ_ERROR
;
7799 return STATUS_READ_ERROR
;
7801 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7803 cp
->status
= STATUS_READ_ERROR
;
7804 return STATUS_READ_ERROR
;
7808 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7810 unsigned long nblock
= 0;
7811 /* We always want this to block, so temporarily disable NDELAY. */
7812 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7813 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7815 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7817 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7820 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7824 if (rc
== sizeof (char))
7825 cp
->status
= STATUS_READ_SUCCEEDED
;
7827 cp
->status
= STATUS_READ_FAILED
;
7833 _sys_wait_accept (int fd
)
7839 if (fd
< 0 || fd
>= MAXDESC
)
7840 return STATUS_READ_ERROR
;
7842 cp
= fd_info
[fd
].cp
;
7844 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7845 return STATUS_READ_ERROR
;
7847 cp
->status
= STATUS_READ_FAILED
;
7849 hEv
= pfn_WSACreateEvent ();
7850 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7851 if (rc
!= SOCKET_ERROR
)
7854 rc
= WaitForSingleObject (hEv
, 500);
7856 } while (rc
== WAIT_TIMEOUT
7857 && cp
->status
!= STATUS_READ_ERROR
7859 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7860 if (rc
== WAIT_OBJECT_0
)
7861 cp
->status
= STATUS_READ_SUCCEEDED
;
7863 pfn_WSACloseEvent (hEv
);
7869 sys_read (int fd
, char * buffer
, unsigned int count
)
7874 char * orig_buffer
= buffer
;
7882 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7884 child_process
*cp
= fd_info
[fd
].cp
;
7886 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7894 /* re-read CR carried over from last read */
7895 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7897 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7901 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7904 /* presence of a child_process structure means we are operating in
7905 non-blocking mode - otherwise we just call _read directly.
7906 Note that the child_process structure might be missing because
7907 reap_subprocess has been called; in this case the pipe is
7908 already broken, so calling _read on it is okay. */
7911 int current_status
= cp
->status
;
7913 switch (current_status
)
7915 case STATUS_READ_FAILED
:
7916 case STATUS_READ_ERROR
:
7917 /* report normal EOF if nothing in buffer */
7919 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7922 case STATUS_READ_READY
:
7923 case STATUS_READ_IN_PROGRESS
:
7924 DebPrint (("sys_read called when read is in progress\n"));
7925 errno
= EWOULDBLOCK
;
7928 case STATUS_READ_SUCCEEDED
:
7929 /* consume read-ahead char */
7930 *buffer
++ = cp
->chr
;
7933 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7934 ResetEvent (cp
->char_avail
);
7936 case STATUS_READ_ACKNOWLEDGED
:
7940 DebPrint (("sys_read: bad status %d\n", current_status
));
7945 if (fd_info
[fd
].flags
& FILE_PIPE
)
7947 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7948 to_read
= min (waiting
, (DWORD
) count
);
7951 nchars
+= _read (fd
, buffer
, to_read
);
7953 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7955 HANDLE hnd
= fd_info
[fd
].hnd
;
7956 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7962 /* Configure timeouts for non-blocking read. */
7963 if (!GetCommTimeouts (hnd
, &ct
))
7968 ct
.ReadIntervalTimeout
= MAXDWORD
;
7969 ct
.ReadTotalTimeoutMultiplier
= 0;
7970 ct
.ReadTotalTimeoutConstant
= 0;
7971 if (!SetCommTimeouts (hnd
, &ct
))
7977 if (!ResetEvent (ovl
->hEvent
))
7982 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
7984 if (GetLastError () != ERROR_IO_PENDING
)
7989 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7998 else /* FILE_SOCKET */
8000 if (winsock_lib
== NULL
) emacs_abort ();
8002 /* do the equivalent of a non-blocking read */
8003 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8004 if (waiting
== 0 && nchars
== 0)
8006 errno
= EWOULDBLOCK
;
8012 /* always use binary mode for sockets */
8013 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8014 if (res
== SOCKET_ERROR
)
8016 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8017 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8027 int nread
= _read (fd
, buffer
, count
);
8030 else if (nchars
== 0)
8035 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8036 /* Perform text mode translation if required. */
8037 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8039 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8040 /* If buffer contains only CR, return that. To be absolutely
8041 sure we should attempt to read the next char, but in
8042 practice a CR to be followed by LF would not appear by
8043 itself in the buffer. */
8044 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8046 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8052 nchars
= _read (fd
, buffer
, count
);
8057 /* From w32xfns.c */
8058 extern HANDLE interrupt_handle
;
8060 /* For now, don't bother with a non-blocking mode */
8062 sys_write (int fd
, const void * buffer
, unsigned int count
)
8072 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8074 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8080 /* Perform text mode translation if required. */
8081 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8083 char * tmpbuf
= alloca (count
* 2);
8084 unsigned char * src
= (void *)buffer
;
8085 unsigned char * dst
= tmpbuf
;
8090 unsigned char *next
;
8091 /* copy next line or remaining bytes */
8092 next
= _memccpy (dst
, src
, '\n', nbytes
);
8095 /* copied one line ending with '\n' */
8096 int copied
= next
- dst
;
8099 /* insert '\r' before '\n' */
8106 /* copied remaining partial line -> now finished */
8113 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8115 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8116 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8117 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8120 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8122 if (GetLastError () != ERROR_IO_PENDING
)
8127 if (detect_input_pending ())
8128 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8131 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8132 if (active
== WAIT_OBJECT_0
)
8133 { /* User pressed C-g, cancel write, then leave. Don't bother
8134 cleaning up as we may only get stuck in buggy drivers. */
8135 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8140 if (active
== WAIT_OBJECT_0
+ 1
8141 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8148 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8150 unsigned long nblock
= 0;
8151 if (winsock_lib
== NULL
) emacs_abort ();
8153 /* TODO: implement select() properly so non-blocking I/O works. */
8154 /* For now, make sure the write blocks. */
8155 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8156 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8158 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8160 /* Set the socket back to non-blocking if it was before,
8161 for other operations that support it. */
8162 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8165 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8168 if (nchars
== SOCKET_ERROR
)
8170 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8171 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8177 /* Some networked filesystems don't like too large writes, so
8178 break them into smaller chunks. See the Comments section of
8179 the MSDN documentation of WriteFile for details behind the
8180 choice of the value of CHUNK below. See also the thread
8181 http://thread.gmane.org/gmane.comp.version-control.git/145294
8182 in the git mailing list. */
8183 const unsigned char *p
= buffer
;
8184 const unsigned chunk
= 30 * 1024 * 1024;
8189 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8190 int n
= _write (fd
, p
, this_chunk
);
8198 else if (n
< this_chunk
)
8209 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8211 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8213 /* Return information about network interface IFNAME, or about all
8214 interfaces (if IFNAME is nil). */
8216 network_interface_get_info (Lisp_Object ifname
)
8218 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8219 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8220 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8221 Lisp_Object res
= Qnil
;
8223 if (retval
== ERROR_BUFFER_OVERFLOW
)
8225 ainfo
= xrealloc (ainfo
, ainfo_len
);
8226 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8229 if (retval
== ERROR_SUCCESS
)
8231 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8232 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8234 struct sockaddr_in sa
;
8236 /* For the below, we need some winsock functions, so make sure
8237 the winsock DLL is loaded. If we cannot successfully load
8238 it, they will have no use of the information we provide,
8240 if (!winsock_lib
&& !init_winsock (1))
8243 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8245 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8247 /* Present Unix-compatible interface names, instead of the
8248 Windows names, which are really GUIDs not readable by
8250 static const char *ifmt
[] = {
8251 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8266 switch (adapter
->Type
)
8268 case MIB_IF_TYPE_ETHERNET
:
8269 /* Windows before Vista reports wireless adapters as
8270 Ethernet. Work around by looking at the Description
8272 if (strstr (adapter
->Description
, "Wireless "))
8275 if_num
= wlan_count
++;
8279 ifmt_idx
= ETHERNET
;
8280 if_num
= eth_count
++;
8283 case MIB_IF_TYPE_TOKENRING
:
8284 ifmt_idx
= TOKENRING
;
8285 if_num
= tr_count
++;
8287 case MIB_IF_TYPE_FDDI
:
8289 if_num
= fddi_count
++;
8291 case MIB_IF_TYPE_PPP
:
8293 if_num
= ppp_count
++;
8295 case MIB_IF_TYPE_SLIP
:
8297 if_num
= sl_count
++;
8299 case IF_TYPE_IEEE80211
:
8301 if_num
= wlan_count
++;
8303 case MIB_IF_TYPE_LOOPBACK
:
8306 ifmt_idx
= LOOPBACK
;
8307 if_num
= lo_count
++;
8313 ifmt_idx
= OTHER_IF
;
8314 if_num
= ifx_count
++;
8317 if (ifmt_idx
== NONE
)
8319 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8321 sa
.sin_family
= AF_INET
;
8322 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8323 if (ip_addr
== INADDR_NONE
)
8325 /* Bogus address, skip this interface. */
8328 sa
.sin_addr
.s_addr
= ip_addr
;
8331 res
= Fcons (Fcons (build_string (namebuf
),
8332 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8333 sizeof (struct sockaddr
))),
8335 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8337 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8338 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8339 Lisp_Object flags
= Qnil
;
8343 /* Flags. We guess most of them by type, since the
8344 Windows flags are different and hard to get by. */
8345 flags
= Fcons (intern ("up"), flags
);
8346 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8348 flags
= Fcons (intern ("broadcast"), flags
);
8349 flags
= Fcons (intern ("multicast"), flags
);
8351 flags
= Fcons (intern ("running"), flags
);
8352 if (ifmt_idx
== PPP
)
8354 flags
= Fcons (intern ("pointopoint"), flags
);
8355 flags
= Fcons (intern ("noarp"), flags
);
8357 if (adapter
->HaveWins
)
8358 flags
= Fcons (intern ("WINS"), flags
);
8359 if (adapter
->DhcpEnabled
)
8360 flags
= Fcons (intern ("dynamic"), flags
);
8362 res
= Fcons (flags
, res
);
8364 /* Hardware address and its family. */
8365 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8366 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8367 /* Windows does not support AF_LINK or AF_PACKET family
8368 of addresses. Use an arbitrary family number that is
8369 identical to what GNU/Linux returns. */
8370 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8373 sa
.sin_family
= AF_INET
;
8374 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8375 if (net_mask
!= INADDR_NONE
)
8377 sa
.sin_addr
.s_addr
= net_mask
;
8379 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8380 sizeof (struct sockaddr
)),
8384 res
= Fcons (Qnil
, res
);
8386 sa
.sin_family
= AF_INET
;
8387 if (ip_addr
!= INADDR_NONE
)
8389 /* Broadcast address is only reported by
8390 GetAdaptersAddresses, which is of limited
8391 availability. Generate it on our own. */
8392 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8394 sa
.sin_addr
.s_addr
= bcast_addr
;
8396 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8397 sizeof (struct sockaddr
)),
8401 sa
.sin_addr
.s_addr
= ip_addr
;
8403 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8404 sizeof (struct sockaddr
)),
8408 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8411 /* GetAdaptersInfo is documented to not report loopback
8412 interfaces, so we generate one out of thin air. */
8415 sa
.sin_family
= AF_INET
;
8419 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8420 res
= Fcons (Fcons (build_string ("lo"),
8421 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8422 sizeof (struct sockaddr
))),
8425 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8427 res
= Fcons (Fcons (intern ("running"),
8428 Fcons (intern ("loopback"),
8429 Fcons (intern ("up"), Qnil
))), Qnil
);
8430 /* 772 is what 3 different GNU/Linux systems report for
8431 the loopback interface. */
8432 res
= Fcons (Fcons (make_number (772),
8433 Fmake_vector (make_number (6),
8436 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8437 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8438 sizeof (struct sockaddr
)),
8440 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8441 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8442 sizeof (struct sockaddr
)),
8444 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8445 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8446 sizeof (struct sockaddr
)),
8459 network_interface_list (void)
8461 return network_interface_get_info (Qnil
);
8465 network_interface_info (Lisp_Object ifname
)
8467 return network_interface_get_info (ifname
);
8471 /* The Windows CRT functions are "optimized for speed", so they don't
8472 check for timezone and DST changes if they were last called less
8473 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8474 all Emacs features that repeatedly call time functions (e.g.,
8475 display-time) are in real danger of missing timezone and DST
8476 changes. Calling tzset before each localtime call fixes that. */
8478 sys_localtime (const time_t *t
)
8481 return localtime (t
);
8486 /* Try loading LIBRARY_ID from the file(s) specified in
8487 Vdynamic_library_alist. If the library is loaded successfully,
8488 return the handle of the DLL, and record the filename in the
8489 property :loaded-from of LIBRARY_ID. If the library could not be
8490 found, or when it was already loaded (because the handle is not
8491 recorded anywhere, and so is lost after use), return NULL.
8493 We could also save the handle in :loaded-from, but currently
8494 there's no use case for it. */
8496 w32_delayed_load (Lisp_Object library_id
)
8498 HMODULE dll_handle
= NULL
;
8500 CHECK_SYMBOL (library_id
);
8502 if (CONSP (Vdynamic_library_alist
)
8503 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8505 Lisp_Object found
= Qnil
;
8506 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8509 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8511 Lisp_Object dll
= XCAR (dlls
);
8512 char name
[MAX_UTF8_PATH
];
8516 dll
= ENCODE_FILE (dll
);
8517 if (w32_unicode_filenames
)
8519 wchar_t name_w
[MAX_PATH
];
8521 filename_to_utf16 (SSDATA (dll
), name_w
);
8522 dll_handle
= LoadLibraryW (name_w
);
8525 res
= GetModuleFileNameW (dll_handle
, name_w
,
8528 filename_from_utf16 (name_w
, name
);
8533 char name_a
[MAX_PATH
];
8535 filename_to_ansi (SSDATA (dll
), name_a
);
8536 dll_handle
= LoadLibraryA (name_a
);
8539 res
= GetModuleFileNameA (dll_handle
, name_a
,
8542 filename_from_ansi (name_a
, name
);
8547 ptrdiff_t len
= strlen (name
);
8550 /* Possibly truncated */
8551 ? make_specified_string (name
, -1, len
, 1)
8557 Fput (library_id
, QCloaded_from
, found
);
8565 check_windows_init_file (void)
8567 /* A common indication that Emacs is not installed properly is when
8568 it cannot find the Windows installation file. If this file does
8569 not exist in the expected place, tell the user. */
8571 if (!noninteractive
&& !inhibit_window_system
8572 /* Vload_path is not yet initialized when we are loading
8574 && NILP (Vpurify_flag
))
8576 Lisp_Object init_file
;
8579 /* Implementation note: this function runs early during Emacs
8580 startup, before startup.el is run. So Vload_path is still in
8581 its initial unibyte form, but it holds UTF-8 encoded file
8582 names, since init_callproc was already called. So we do not
8583 need to ENCODE_FILE here, but we do need to convert the file
8584 names from UTF-8 to ANSI. */
8585 init_file
= build_string ("term/w32-win");
8586 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
8589 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8590 char *init_file_name
= SDATA (init_file
);
8591 char *load_path
= SDATA (load_path_print
);
8592 char *buffer
= alloca (1024
8593 + strlen (init_file_name
)
8594 + strlen (load_path
));
8599 "The Emacs Windows initialization file \"%s.el\" "
8600 "could not be found in your Emacs installation. "
8601 "Emacs checked the following directories for this file:\n"
8603 "When Emacs cannot find this file, it usually means that it "
8604 "was not installed properly, or its distribution file was "
8605 "not unpacked properly.\nSee the README.W32 file in the "
8606 "top-level Emacs directory for more information.",
8607 init_file_name
, load_path
);
8608 needed
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8612 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8614 MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8616 needed
= WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8617 NULL
, 0, NULL
, NULL
);
8620 char *msg_a
= alloca (needed
+ 1);
8622 WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8629 "Emacs Abort Dialog",
8630 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8631 /* Use the low-level system abort. */
8642 term_ntproc (int ignored
)
8648 /* shutdown the socket interface if necessary */
8655 init_ntproc (int dumping
)
8657 sigset_t initial_mask
= 0;
8659 /* Initialize the socket interface now if available and requested by
8660 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8661 delayed until open-network-stream is called (w32-has-winsock can
8662 also be used to dynamically load or reload winsock).
8664 Conveniently, init_environment is called before us, so
8665 PRELOAD_WINSOCK can be set in the registry. */
8667 /* Always initialize this correctly. */
8670 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8671 init_winsock (TRUE
);
8673 /* Initial preparation for subprocess support: replace our standard
8674 handles with non-inheritable versions. */
8677 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8678 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8679 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8681 parent
= GetCurrentProcess ();
8683 /* ignore errors when duplicating and closing; typically the
8684 handles will be invalid when running as a gui program. */
8685 DuplicateHandle (parent
,
8686 GetStdHandle (STD_INPUT_HANDLE
),
8691 DUPLICATE_SAME_ACCESS
);
8693 DuplicateHandle (parent
,
8694 GetStdHandle (STD_OUTPUT_HANDLE
),
8699 DUPLICATE_SAME_ACCESS
);
8701 DuplicateHandle (parent
,
8702 GetStdHandle (STD_ERROR_HANDLE
),
8707 DUPLICATE_SAME_ACCESS
);
8713 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8714 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8716 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8719 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8720 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8722 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8725 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8726 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8728 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8732 /* unfortunately, atexit depends on implementation of malloc */
8733 /* atexit (term_ntproc); */
8736 /* Make sure we start with all signals unblocked. */
8737 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8738 signal (SIGABRT
, term_ntproc
);
8742 /* determine which drives are fixed, for GetCachedVolumeInformation */
8744 /* GetDriveType must have trailing backslash. */
8745 char drive
[] = "A:\\";
8747 /* Loop over all possible drive letters */
8748 while (*drive
<= 'Z')
8750 /* Record if this drive letter refers to a fixed drive. */
8751 fixed_drives
[DRIVE_INDEX (*drive
)] =
8752 (GetDriveType (drive
) == DRIVE_FIXED
);
8757 /* Reset the volume info cache. */
8758 volume_cache
= NULL
;
8763 shutdown_handler ensures that buffers' autosave files are
8764 up to date when the user logs off, or the system shuts down.
8767 shutdown_handler (DWORD type
)
8769 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8770 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8771 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8772 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8774 /* Shut down cleanly, making sure autosave files are up to date. */
8775 shut_down_emacs (0, Qnil
);
8778 /* Allow other handlers to handle this signal. */
8783 globals_of_w32 is used to initialize those global variables that
8784 must always be initialized on startup even when the global variable
8785 initialized is non zero (see the function main in emacs.c).
8788 globals_of_w32 (void)
8790 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8792 get_process_times_fn
= (GetProcessTimes_Proc
)
8793 GetProcAddress (kernel32
, "GetProcessTimes");
8795 DEFSYM (QCloaded_from
, ":loaded-from");
8797 g_b_init_is_windows_9x
= 0;
8798 g_b_init_open_process_token
= 0;
8799 g_b_init_get_token_information
= 0;
8800 g_b_init_lookup_account_sid
= 0;
8801 g_b_init_get_sid_sub_authority
= 0;
8802 g_b_init_get_sid_sub_authority_count
= 0;
8803 g_b_init_get_security_info
= 0;
8804 g_b_init_get_file_security_w
= 0;
8805 g_b_init_get_file_security_a
= 0;
8806 g_b_init_get_security_descriptor_owner
= 0;
8807 g_b_init_get_security_descriptor_group
= 0;
8808 g_b_init_is_valid_sid
= 0;
8809 g_b_init_create_toolhelp32_snapshot
= 0;
8810 g_b_init_process32_first
= 0;
8811 g_b_init_process32_next
= 0;
8812 g_b_init_open_thread_token
= 0;
8813 g_b_init_impersonate_self
= 0;
8814 g_b_init_revert_to_self
= 0;
8815 g_b_init_get_process_memory_info
= 0;
8816 g_b_init_get_process_working_set_size
= 0;
8817 g_b_init_global_memory_status
= 0;
8818 g_b_init_global_memory_status_ex
= 0;
8819 g_b_init_equal_sid
= 0;
8820 g_b_init_copy_sid
= 0;
8821 g_b_init_get_length_sid
= 0;
8822 g_b_init_get_native_system_info
= 0;
8823 g_b_init_get_system_times
= 0;
8824 g_b_init_create_symbolic_link_w
= 0;
8825 g_b_init_create_symbolic_link_a
= 0;
8826 g_b_init_get_security_descriptor_dacl
= 0;
8827 g_b_init_convert_sd_to_sddl
= 0;
8828 g_b_init_convert_sddl_to_sd
= 0;
8829 g_b_init_is_valid_security_descriptor
= 0;
8830 g_b_init_set_file_security_w
= 0;
8831 g_b_init_set_file_security_a
= 0;
8832 g_b_init_get_adapters_info
= 0;
8833 num_of_processors
= 0;
8834 /* The following sets a handler for shutdown notifications for
8835 console apps. This actually applies to Emacs in both console and
8836 GUI modes, since we had to fool windows into thinking emacs is a
8837 console application to get console mode to work. */
8838 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8840 /* "None" is the default group name on standalone workstations. */
8841 strcpy (dflt_group_name
, "None");
8843 /* Reset, in case it has some value inherited from dump time. */
8844 w32_stat_get_owner_group
= 0;
8846 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8847 (a.k.a. "wide") APIs to invoke functions that accept file
8849 if (is_windows_9x ())
8850 w32_unicode_filenames
= 0;
8852 w32_unicode_filenames
= 1;
8855 /* For make-serial-process */
8857 serial_open (Lisp_Object port_obj
)
8859 char *port
= SSDATA (port_obj
);
8864 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8865 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8866 if (hnd
== INVALID_HANDLE_VALUE
)
8867 error ("Could not open %s", port
);
8868 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8870 error ("Could not open %s", port
);
8874 error ("Could not create child process");
8876 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8877 fd_info
[ fd
].hnd
= hnd
;
8878 fd_info
[ fd
].flags
|=
8879 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8880 if (fd_info
[ fd
].cp
!= NULL
)
8882 error ("fd_info[fd = %d] is already in use", fd
);
8884 fd_info
[ fd
].cp
= cp
;
8885 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8886 if (cp
->ovl_read
.hEvent
== NULL
)
8887 error ("Could not create read event");
8888 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8889 if (cp
->ovl_write
.hEvent
== NULL
)
8890 error ("Could not create write event");
8895 /* For serial-process-configure */
8897 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8899 Lisp_Object childp2
= Qnil
;
8900 Lisp_Object tem
= Qnil
;
8904 char summary
[4] = "???"; /* This usually becomes "8N1". */
8906 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8907 error ("Not a serial process");
8908 hnd
= fd_info
[ p
->outfd
].hnd
;
8910 childp2
= Fcopy_sequence (p
->childp
);
8912 /* Initialize timeouts for blocking read and blocking write. */
8913 if (!GetCommTimeouts (hnd
, &ct
))
8914 error ("GetCommTimeouts() failed");
8915 ct
.ReadIntervalTimeout
= 0;
8916 ct
.ReadTotalTimeoutMultiplier
= 0;
8917 ct
.ReadTotalTimeoutConstant
= 0;
8918 ct
.WriteTotalTimeoutMultiplier
= 0;
8919 ct
.WriteTotalTimeoutConstant
= 0;
8920 if (!SetCommTimeouts (hnd
, &ct
))
8921 error ("SetCommTimeouts() failed");
8922 /* Read port attributes and prepare default configuration. */
8923 memset (&dcb
, 0, sizeof (dcb
));
8924 dcb
.DCBlength
= sizeof (DCB
);
8925 if (!GetCommState (hnd
, &dcb
))
8926 error ("GetCommState() failed");
8929 dcb
.fAbortOnError
= FALSE
;
8930 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8935 /* Configure speed. */
8936 if (!NILP (Fplist_member (contact
, QCspeed
)))
8937 tem
= Fplist_get (contact
, QCspeed
);
8939 tem
= Fplist_get (p
->childp
, QCspeed
);
8941 dcb
.BaudRate
= XINT (tem
);
8942 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8944 /* Configure bytesize. */
8945 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8946 tem
= Fplist_get (contact
, QCbytesize
);
8948 tem
= Fplist_get (p
->childp
, QCbytesize
);
8950 tem
= make_number (8);
8952 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8953 error (":bytesize must be nil (8), 7, or 8");
8954 dcb
.ByteSize
= XINT (tem
);
8955 summary
[0] = XINT (tem
) + '0';
8956 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8958 /* Configure parity. */
8959 if (!NILP (Fplist_member (contact
, QCparity
)))
8960 tem
= Fplist_get (contact
, QCparity
);
8962 tem
= Fplist_get (p
->childp
, QCparity
);
8963 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8964 error (":parity must be nil (no parity), `even', or `odd'");
8965 dcb
.fParity
= FALSE
;
8966 dcb
.Parity
= NOPARITY
;
8967 dcb
.fErrorChar
= FALSE
;
8972 else if (EQ (tem
, Qeven
))
8976 dcb
.Parity
= EVENPARITY
;
8977 dcb
.fErrorChar
= TRUE
;
8979 else if (EQ (tem
, Qodd
))
8983 dcb
.Parity
= ODDPARITY
;
8984 dcb
.fErrorChar
= TRUE
;
8986 childp2
= Fplist_put (childp2
, QCparity
, tem
);
8988 /* Configure stopbits. */
8989 if (!NILP (Fplist_member (contact
, QCstopbits
)))
8990 tem
= Fplist_get (contact
, QCstopbits
);
8992 tem
= Fplist_get (p
->childp
, QCstopbits
);
8994 tem
= make_number (1);
8996 if (XINT (tem
) != 1 && XINT (tem
) != 2)
8997 error (":stopbits must be nil (1 stopbit), 1, or 2");
8998 summary
[2] = XINT (tem
) + '0';
8999 if (XINT (tem
) == 1)
9000 dcb
.StopBits
= ONESTOPBIT
;
9001 else if (XINT (tem
) == 2)
9002 dcb
.StopBits
= TWOSTOPBITS
;
9003 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9005 /* Configure flowcontrol. */
9006 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9007 tem
= Fplist_get (contact
, QCflowcontrol
);
9009 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9010 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9011 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9012 dcb
.fOutxCtsFlow
= FALSE
;
9013 dcb
.fOutxDsrFlow
= FALSE
;
9014 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9015 dcb
.fDsrSensitivity
= FALSE
;
9016 dcb
.fTXContinueOnXoff
= FALSE
;
9019 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9020 dcb
.XonChar
= 17; /* Control-Q */
9021 dcb
.XoffChar
= 19; /* Control-S */
9024 /* Already configured. */
9026 else if (EQ (tem
, Qhw
))
9028 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9029 dcb
.fOutxCtsFlow
= TRUE
;
9031 else if (EQ (tem
, Qsw
))
9036 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9038 /* Activate configuration. */
9039 if (!SetCommState (hnd
, &dcb
))
9040 error ("SetCommState() failed");
9042 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9043 pset_childp (p
, childp2
);
9049 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9053 struct timespec timeout
;
9054 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9055 int fd
= process
->infd
;
9057 n
= sys_read (fd
, (char*)buf
, sz
);
9064 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9065 if (err
== EWOULDBLOCK
)
9068 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9074 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9076 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9077 int fd
= process
->outfd
;
9078 ssize_t n
= sys_write (fd
, buf
, sz
);
9080 /* 0 or more bytes written means everything went fine. */
9084 /* Negative bytes written means we got an error in errno.
9085 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9086 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9087 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9091 #endif /* HAVE_GNUTLS */