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>
144 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
145 define them by hand if not already defined. */
146 #ifndef SDDL_REVISION_1
147 #define SDDL_REVISION_1 1
148 #endif /* SDDL_REVISION_1 */
150 #if defined(_MSC_VER) || defined(_W64)
151 /* MSVC and MinGW64 don't provide the definition of
152 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
153 which cannot be included because it triggers conflicts with other
154 Windows API headers. So we define it here by hand. */
156 typedef struct _REPARSE_DATA_BUFFER
{
158 USHORT ReparseDataLength
;
162 USHORT SubstituteNameOffset
;
163 USHORT SubstituteNameLength
;
164 USHORT PrintNameOffset
;
165 USHORT PrintNameLength
;
168 } SymbolicLinkReparseBuffer
;
170 USHORT SubstituteNameOffset
;
171 USHORT SubstituteNameLength
;
172 USHORT PrintNameOffset
;
173 USHORT PrintNameLength
;
175 } MountPointReparseBuffer
;
178 } GenericReparseBuffer
;
180 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
182 #ifndef FILE_DEVICE_FILE_SYSTEM
183 #define FILE_DEVICE_FILE_SYSTEM 9
185 #ifndef METHOD_BUFFERED
186 #define METHOD_BUFFERED 0
188 #ifndef FILE_ANY_ACCESS
189 #define FILE_ANY_ACCESS 0x00000000
192 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
194 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
195 #ifndef FSCTL_GET_REPARSE_POINT
196 #define FSCTL_GET_REPARSE_POINT \
197 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
201 /* TCP connection support. */
202 #include <sys/socket.h>
221 #include <iphlpapi.h> /* should be after winsock2.h */
225 #include "w32common.h"
227 #include "w32select.h"
229 #include "dispextern.h" /* for xstrcasecmp */
230 #include "coding.h" /* for Vlocale_coding_system */
232 #include "careadlinkat.h"
233 #include "allocator.h"
235 /* For serial_configure and serial_open. */
238 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
239 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
241 Lisp_Object QCloaded_from
;
243 void globals_of_w32 (void);
244 static DWORD
get_rid (PSID
);
245 static int is_symlink (const char *);
246 static char * chase_symlinks (const char *);
247 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
248 static int restore_privilege (TOKEN_PRIVILEGES
*);
249 static BOOL WINAPI
revert_to_self (void);
251 static int sys_access (const char *, int);
252 extern void *e_malloc (size_t);
253 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
254 struct timespec
*, void *);
255 extern int sys_dup (int);
260 /* Initialization states.
262 WARNING: If you add any more such variables for additional APIs,
263 you MUST add initialization for them to globals_of_w32
264 below. This is because these variables might get set
265 to non-NULL values during dumping, but the dumped Emacs
266 cannot reuse those values, because it could be run on a
267 different version of the OS, where API addresses are
269 static BOOL g_b_init_is_windows_9x
;
270 static BOOL g_b_init_open_process_token
;
271 static BOOL g_b_init_get_token_information
;
272 static BOOL g_b_init_lookup_account_sid
;
273 static BOOL g_b_init_get_sid_sub_authority
;
274 static BOOL g_b_init_get_sid_sub_authority_count
;
275 static BOOL g_b_init_get_security_info
;
276 static BOOL g_b_init_get_file_security_w
;
277 static BOOL g_b_init_get_file_security_a
;
278 static BOOL g_b_init_get_security_descriptor_owner
;
279 static BOOL g_b_init_get_security_descriptor_group
;
280 static BOOL g_b_init_is_valid_sid
;
281 static BOOL g_b_init_create_toolhelp32_snapshot
;
282 static BOOL g_b_init_process32_first
;
283 static BOOL g_b_init_process32_next
;
284 static BOOL g_b_init_open_thread_token
;
285 static BOOL g_b_init_impersonate_self
;
286 static BOOL g_b_init_revert_to_self
;
287 static BOOL g_b_init_get_process_memory_info
;
288 static BOOL g_b_init_get_process_working_set_size
;
289 static BOOL g_b_init_global_memory_status
;
290 static BOOL g_b_init_global_memory_status_ex
;
291 static BOOL g_b_init_get_length_sid
;
292 static BOOL g_b_init_equal_sid
;
293 static BOOL g_b_init_copy_sid
;
294 static BOOL g_b_init_get_native_system_info
;
295 static BOOL g_b_init_get_system_times
;
296 static BOOL g_b_init_create_symbolic_link_w
;
297 static BOOL g_b_init_create_symbolic_link_a
;
298 static BOOL g_b_init_get_security_descriptor_dacl
;
299 static BOOL g_b_init_convert_sd_to_sddl
;
300 static BOOL g_b_init_convert_sddl_to_sd
;
301 static BOOL g_b_init_is_valid_security_descriptor
;
302 static BOOL g_b_init_set_file_security_w
;
303 static BOOL g_b_init_set_file_security_a
;
304 static BOOL g_b_init_get_adapters_info
;
307 BEGIN: Wrapper functions around OpenProcessToken
308 and other functions in advapi32.dll that are only
309 supported in Windows NT / 2k / XP
311 /* ** Function pointer typedefs ** */
312 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
313 HANDLE ProcessHandle
,
315 PHANDLE TokenHandle
);
316 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
318 TOKEN_INFORMATION_CLASS TokenInformationClass
,
319 LPVOID TokenInformation
,
320 DWORD TokenInformationLength
,
321 PDWORD ReturnLength
);
322 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
323 HANDLE process_handle
,
324 LPFILETIME creation_time
,
325 LPFILETIME exit_time
,
326 LPFILETIME kernel_time
,
327 LPFILETIME user_time
);
329 GetProcessTimes_Proc get_process_times_fn
= NULL
;
332 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
334 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
336 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
337 LPCTSTR lpSystemName
,
342 LPDWORD cbDomainName
,
343 PSID_NAME_USE peUse
);
344 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
347 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
349 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
351 SE_OBJECT_TYPE ObjectType
,
352 SECURITY_INFORMATION SecurityInfo
,
357 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
358 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
360 SECURITY_INFORMATION RequestedInformation
,
361 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
363 LPDWORD lpnLengthNeeded
);
364 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
366 SECURITY_INFORMATION RequestedInformation
,
367 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
369 LPDWORD lpnLengthNeeded
);
370 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
372 SECURITY_INFORMATION SecurityInformation
,
373 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
374 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
376 SECURITY_INFORMATION SecurityInformation
,
377 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
378 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
379 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
381 LPBOOL lpbOwnerDefaulted
);
382 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
383 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
385 LPBOOL lpbGroupDefaulted
);
386 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
387 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
388 LPBOOL lpbDaclPresent
,
390 LPBOOL lpbDaclDefaulted
);
391 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
393 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
395 DWORD th32ProcessID
);
396 typedef BOOL (WINAPI
* Process32First_Proc
) (
398 LPPROCESSENTRY32 lppe
);
399 typedef BOOL (WINAPI
* Process32Next_Proc
) (
401 LPPROCESSENTRY32 lppe
);
402 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
406 PHANDLE TokenHandle
);
407 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
408 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
409 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
410 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
412 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
414 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
416 PSIZE_T lpMinimumWorkingSetSize
,
417 PSIZE_T lpMaximumWorkingSetSize
);
418 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
419 LPMEMORYSTATUS lpBuffer
);
420 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
421 LPMEMORY_STATUS_EX lpBuffer
);
422 typedef BOOL (WINAPI
* CopySid_Proc
) (
423 DWORD nDestinationSidLength
,
424 PSID pDestinationSid
,
426 typedef BOOL (WINAPI
* EqualSid_Proc
) (
429 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
431 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
432 LPSYSTEM_INFO lpSystemInfo
);
433 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
434 LPFILETIME lpIdleTime
,
435 LPFILETIME lpKernelTime
,
436 LPFILETIME lpUserTime
);
437 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
438 LPCWSTR lpSymlinkFileName
,
439 LPCWSTR lpTargetFileName
,
441 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
442 LPCSTR lpSymlinkFileName
,
443 LPCSTR lpTargetFileName
,
445 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
446 LPCTSTR StringSecurityDescriptor
,
447 DWORD StringSDRevision
,
448 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
449 PULONG SecurityDescriptorSize
);
450 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
451 PSECURITY_DESCRIPTOR SecurityDescriptor
,
452 DWORD RequestedStringSDRevision
,
453 SECURITY_INFORMATION SecurityInformation
,
454 LPTSTR
*StringSecurityDescriptor
,
455 PULONG StringSecurityDescriptorLen
);
456 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
457 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
458 PIP_ADAPTER_INFO pAdapterInfo
,
461 /* ** A utility function ** */
465 static BOOL s_b_ret
= 0;
466 OSVERSIONINFO os_ver
;
467 if (g_b_init_is_windows_9x
== 0)
469 g_b_init_is_windows_9x
= 1;
470 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
471 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
472 if (GetVersionEx (&os_ver
))
474 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
480 static Lisp_Object
ltime (ULONGLONG
);
482 /* Get total user and system times for get-internal-run-time.
483 Returns a list of integers if the times are provided by the OS
484 (NT derivatives), otherwise it returns the result of current-time. */
486 w32_get_internal_run_time (void)
488 if (get_process_times_fn
)
490 FILETIME create
, exit
, kernel
, user
;
491 HANDLE proc
= GetCurrentProcess ();
492 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
494 LARGE_INTEGER user_int
, kernel_int
, total
;
495 user_int
.LowPart
= user
.dwLowDateTime
;
496 user_int
.HighPart
= user
.dwHighDateTime
;
497 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
498 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
499 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
500 return ltime (total
.QuadPart
);
504 return Fcurrent_time ();
507 /* ** The wrapper functions ** */
510 open_process_token (HANDLE ProcessHandle
,
514 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
515 HMODULE hm_advapi32
= NULL
;
516 if (is_windows_9x () == TRUE
)
520 if (g_b_init_open_process_token
== 0)
522 g_b_init_open_process_token
= 1;
523 hm_advapi32
= LoadLibrary ("Advapi32.dll");
524 s_pfn_Open_Process_Token
=
525 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
527 if (s_pfn_Open_Process_Token
== NULL
)
532 s_pfn_Open_Process_Token (
540 get_token_information (HANDLE TokenHandle
,
541 TOKEN_INFORMATION_CLASS TokenInformationClass
,
542 LPVOID TokenInformation
,
543 DWORD TokenInformationLength
,
546 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
547 HMODULE hm_advapi32
= NULL
;
548 if (is_windows_9x () == TRUE
)
552 if (g_b_init_get_token_information
== 0)
554 g_b_init_get_token_information
= 1;
555 hm_advapi32
= LoadLibrary ("Advapi32.dll");
556 s_pfn_Get_Token_Information
=
557 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
559 if (s_pfn_Get_Token_Information
== NULL
)
564 s_pfn_Get_Token_Information (
566 TokenInformationClass
,
568 TokenInformationLength
,
574 lookup_account_sid (LPCTSTR lpSystemName
,
579 LPDWORD cbDomainName
,
582 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
583 HMODULE hm_advapi32
= NULL
;
584 if (is_windows_9x () == TRUE
)
588 if (g_b_init_lookup_account_sid
== 0)
590 g_b_init_lookup_account_sid
= 1;
591 hm_advapi32
= LoadLibrary ("Advapi32.dll");
592 s_pfn_Lookup_Account_Sid
=
593 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
595 if (s_pfn_Lookup_Account_Sid
== NULL
)
600 s_pfn_Lookup_Account_Sid (
612 get_sid_sub_authority (PSID pSid
, DWORD n
)
614 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
615 static DWORD zero
= 0U;
616 HMODULE hm_advapi32
= NULL
;
617 if (is_windows_9x () == TRUE
)
621 if (g_b_init_get_sid_sub_authority
== 0)
623 g_b_init_get_sid_sub_authority
= 1;
624 hm_advapi32
= LoadLibrary ("Advapi32.dll");
625 s_pfn_Get_Sid_Sub_Authority
=
626 (GetSidSubAuthority_Proc
) GetProcAddress (
627 hm_advapi32
, "GetSidSubAuthority");
629 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
633 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
637 get_sid_sub_authority_count (PSID pSid
)
639 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
640 static UCHAR zero
= 0U;
641 HMODULE hm_advapi32
= NULL
;
642 if (is_windows_9x () == TRUE
)
646 if (g_b_init_get_sid_sub_authority_count
== 0)
648 g_b_init_get_sid_sub_authority_count
= 1;
649 hm_advapi32
= LoadLibrary ("Advapi32.dll");
650 s_pfn_Get_Sid_Sub_Authority_Count
=
651 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
652 hm_advapi32
, "GetSidSubAuthorityCount");
654 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
658 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
662 get_security_info (HANDLE handle
,
663 SE_OBJECT_TYPE ObjectType
,
664 SECURITY_INFORMATION SecurityInfo
,
669 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
671 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
672 HMODULE hm_advapi32
= NULL
;
673 if (is_windows_9x () == TRUE
)
677 if (g_b_init_get_security_info
== 0)
679 g_b_init_get_security_info
= 1;
680 hm_advapi32
= LoadLibrary ("Advapi32.dll");
681 s_pfn_Get_Security_Info
=
682 (GetSecurityInfo_Proc
) GetProcAddress (
683 hm_advapi32
, "GetSecurityInfo");
685 if (s_pfn_Get_Security_Info
== NULL
)
689 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
690 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
691 ppSecurityDescriptor
));
695 get_file_security (const char *lpFileName
,
696 SECURITY_INFORMATION RequestedInformation
,
697 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
699 LPDWORD lpnLengthNeeded
)
701 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
702 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
703 HMODULE hm_advapi32
= NULL
;
704 if (is_windows_9x () == TRUE
)
709 if (w32_unicode_filenames
)
711 wchar_t filename_w
[MAX_PATH
];
713 if (g_b_init_get_file_security_w
== 0)
715 g_b_init_get_file_security_w
= 1;
716 hm_advapi32
= LoadLibrary ("Advapi32.dll");
717 s_pfn_Get_File_SecurityW
=
718 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
721 if (s_pfn_Get_File_SecurityW
== NULL
)
726 filename_to_utf16 (lpFileName
, filename_w
);
727 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
728 pSecurityDescriptor
, nLength
,
733 char filename_a
[MAX_PATH
];
735 if (g_b_init_get_file_security_a
== 0)
737 g_b_init_get_file_security_a
= 1;
738 hm_advapi32
= LoadLibrary ("Advapi32.dll");
739 s_pfn_Get_File_SecurityA
=
740 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
743 if (s_pfn_Get_File_SecurityA
== NULL
)
748 filename_to_ansi (lpFileName
, filename_a
);
749 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
750 pSecurityDescriptor
, nLength
,
756 set_file_security (const char *lpFileName
,
757 SECURITY_INFORMATION SecurityInformation
,
758 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
760 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
761 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
762 HMODULE hm_advapi32
= NULL
;
763 if (is_windows_9x () == TRUE
)
768 if (w32_unicode_filenames
)
770 wchar_t filename_w
[MAX_PATH
];
772 if (g_b_init_set_file_security_w
== 0)
774 g_b_init_set_file_security_w
= 1;
775 hm_advapi32
= LoadLibrary ("Advapi32.dll");
776 s_pfn_Set_File_SecurityW
=
777 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
780 if (s_pfn_Set_File_SecurityW
== NULL
)
785 filename_to_utf16 (lpFileName
, filename_w
);
786 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
787 pSecurityDescriptor
));
791 char filename_a
[MAX_PATH
];
793 if (g_b_init_set_file_security_a
== 0)
795 g_b_init_set_file_security_a
= 1;
796 hm_advapi32
= LoadLibrary ("Advapi32.dll");
797 s_pfn_Set_File_SecurityA
=
798 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
801 if (s_pfn_Set_File_SecurityA
== NULL
)
806 filename_to_ansi (lpFileName
, filename_a
);
807 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
808 pSecurityDescriptor
));
813 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
815 LPBOOL lpbOwnerDefaulted
)
817 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
818 HMODULE hm_advapi32
= NULL
;
819 if (is_windows_9x () == TRUE
)
824 if (g_b_init_get_security_descriptor_owner
== 0)
826 g_b_init_get_security_descriptor_owner
= 1;
827 hm_advapi32
= LoadLibrary ("Advapi32.dll");
828 s_pfn_Get_Security_Descriptor_Owner
=
829 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
830 hm_advapi32
, "GetSecurityDescriptorOwner");
832 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
837 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
842 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
844 LPBOOL lpbGroupDefaulted
)
846 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
847 HMODULE hm_advapi32
= NULL
;
848 if (is_windows_9x () == TRUE
)
853 if (g_b_init_get_security_descriptor_group
== 0)
855 g_b_init_get_security_descriptor_group
= 1;
856 hm_advapi32
= LoadLibrary ("Advapi32.dll");
857 s_pfn_Get_Security_Descriptor_Group
=
858 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
859 hm_advapi32
, "GetSecurityDescriptorGroup");
861 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
866 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
871 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
872 LPBOOL lpbDaclPresent
,
874 LPBOOL lpbDaclDefaulted
)
876 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
877 HMODULE hm_advapi32
= NULL
;
878 if (is_windows_9x () == TRUE
)
883 if (g_b_init_get_security_descriptor_dacl
== 0)
885 g_b_init_get_security_descriptor_dacl
= 1;
886 hm_advapi32
= LoadLibrary ("Advapi32.dll");
887 s_pfn_Get_Security_Descriptor_Dacl
=
888 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
889 hm_advapi32
, "GetSecurityDescriptorDacl");
891 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
896 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
897 lpbDaclPresent
, pDacl
,
902 is_valid_sid (PSID sid
)
904 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
905 HMODULE hm_advapi32
= NULL
;
906 if (is_windows_9x () == TRUE
)
910 if (g_b_init_is_valid_sid
== 0)
912 g_b_init_is_valid_sid
= 1;
913 hm_advapi32
= LoadLibrary ("Advapi32.dll");
915 (IsValidSid_Proc
) GetProcAddress (
916 hm_advapi32
, "IsValidSid");
918 if (s_pfn_Is_Valid_Sid
== NULL
)
922 return (s_pfn_Is_Valid_Sid (sid
));
926 equal_sid (PSID sid1
, PSID sid2
)
928 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
929 HMODULE hm_advapi32
= NULL
;
930 if (is_windows_9x () == TRUE
)
934 if (g_b_init_equal_sid
== 0)
936 g_b_init_equal_sid
= 1;
937 hm_advapi32
= LoadLibrary ("Advapi32.dll");
939 (EqualSid_Proc
) GetProcAddress (
940 hm_advapi32
, "EqualSid");
942 if (s_pfn_Equal_Sid
== NULL
)
946 return (s_pfn_Equal_Sid (sid1
, sid2
));
950 get_length_sid (PSID sid
)
952 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
953 HMODULE hm_advapi32
= NULL
;
954 if (is_windows_9x () == TRUE
)
958 if (g_b_init_get_length_sid
== 0)
960 g_b_init_get_length_sid
= 1;
961 hm_advapi32
= LoadLibrary ("Advapi32.dll");
962 s_pfn_Get_Length_Sid
=
963 (GetLengthSid_Proc
) GetProcAddress (
964 hm_advapi32
, "GetLengthSid");
966 if (s_pfn_Get_Length_Sid
== NULL
)
970 return (s_pfn_Get_Length_Sid (sid
));
974 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
976 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
977 HMODULE hm_advapi32
= NULL
;
978 if (is_windows_9x () == TRUE
)
982 if (g_b_init_copy_sid
== 0)
984 g_b_init_copy_sid
= 1;
985 hm_advapi32
= LoadLibrary ("Advapi32.dll");
987 (CopySid_Proc
) GetProcAddress (
988 hm_advapi32
, "CopySid");
990 if (s_pfn_Copy_Sid
== NULL
)
994 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
998 END: Wrapper functions around OpenProcessToken
999 and other functions in advapi32.dll that are only
1000 supported in Windows NT / 2k / XP
1004 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1006 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1007 if (is_windows_9x () != TRUE
)
1009 if (g_b_init_get_native_system_info
== 0)
1011 g_b_init_get_native_system_info
= 1;
1012 s_pfn_Get_Native_System_Info
=
1013 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1014 "GetNativeSystemInfo");
1016 if (s_pfn_Get_Native_System_Info
!= NULL
)
1017 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1020 lpSystemInfo
->dwNumberOfProcessors
= -1;
1024 get_system_times (LPFILETIME lpIdleTime
,
1025 LPFILETIME lpKernelTime
,
1026 LPFILETIME lpUserTime
)
1028 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1029 if (is_windows_9x () == TRUE
)
1033 if (g_b_init_get_system_times
== 0)
1035 g_b_init_get_system_times
= 1;
1036 s_pfn_Get_System_times
=
1037 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1040 if (s_pfn_Get_System_times
== NULL
)
1042 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1045 static BOOLEAN WINAPI
1046 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1047 LPCSTR lpTargetFileName
,
1050 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1051 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1054 if (is_windows_9x () == TRUE
)
1059 if (w32_unicode_filenames
)
1061 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1063 if (g_b_init_create_symbolic_link_w
== 0)
1065 g_b_init_create_symbolic_link_w
= 1;
1066 s_pfn_Create_Symbolic_LinkW
=
1067 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1068 "CreateSymbolicLinkW");
1070 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1076 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1077 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1078 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1079 /* If we were denied creation of the symlink, try again after
1080 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1083 TOKEN_PRIVILEGES priv_current
;
1085 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1088 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1089 restore_privilege (&priv_current
);
1096 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1098 if (g_b_init_create_symbolic_link_a
== 0)
1100 g_b_init_create_symbolic_link_a
= 1;
1101 s_pfn_Create_Symbolic_LinkA
=
1102 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1103 "CreateSymbolicLinkA");
1105 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1111 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1112 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1113 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1114 /* If we were denied creation of the symlink, try again after
1115 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1118 TOKEN_PRIVILEGES priv_current
;
1120 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1123 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1124 restore_privilege (&priv_current
);
1133 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1135 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1137 if (is_windows_9x () == TRUE
)
1143 if (g_b_init_is_valid_security_descriptor
== 0)
1145 g_b_init_is_valid_security_descriptor
= 1;
1146 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1147 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1148 "IsValidSecurityDescriptor");
1150 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1156 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1160 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1161 DWORD RequestedStringSDRevision
,
1162 SECURITY_INFORMATION SecurityInformation
,
1163 LPTSTR
*StringSecurityDescriptor
,
1164 PULONG StringSecurityDescriptorLen
)
1166 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1169 if (is_windows_9x () == TRUE
)
1175 if (g_b_init_convert_sd_to_sddl
== 0)
1177 g_b_init_convert_sd_to_sddl
= 1;
1179 s_pfn_Convert_SD_To_SDDL
=
1180 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1181 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1183 s_pfn_Convert_SD_To_SDDL
=
1184 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1185 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1188 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1194 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1195 RequestedStringSDRevision
,
1196 SecurityInformation
,
1197 StringSecurityDescriptor
,
1198 StringSecurityDescriptorLen
);
1204 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1205 DWORD StringSDRevision
,
1206 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1207 PULONG SecurityDescriptorSize
)
1209 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1212 if (is_windows_9x () == TRUE
)
1218 if (g_b_init_convert_sddl_to_sd
== 0)
1220 g_b_init_convert_sddl_to_sd
= 1;
1222 s_pfn_Convert_SDDL_To_SD
=
1223 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1224 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1226 s_pfn_Convert_SDDL_To_SD
=
1227 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1228 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1231 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1237 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1240 SecurityDescriptorSize
);
1246 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1248 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1249 HMODULE hm_iphlpapi
= NULL
;
1251 if (is_windows_9x () == TRUE
)
1252 return ERROR_NOT_SUPPORTED
;
1254 if (g_b_init_get_adapters_info
== 0)
1256 g_b_init_get_adapters_info
= 1;
1257 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1259 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1260 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1262 if (s_pfn_Get_Adapters_Info
== NULL
)
1263 return ERROR_NOT_SUPPORTED
;
1264 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1269 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1270 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1272 This is called from alloc.c:valid_pointer_p. */
1274 w32_valid_pointer_p (void *p
, int size
)
1277 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1281 unsigned char *buf
= alloca (size
);
1282 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1293 /* Here's an overview of how the Windows build supports file names
1294 that cannot be encoded by the current system codepage.
1296 From the POV of Lisp and layers of C code above the functions here,
1297 Emacs on Windows pretends that its file names are encoded in UTF-8;
1298 see encode_file and decode_file on coding.c. Any file name that is
1299 passed as a unibyte string to C functions defined here is assumed
1300 to be in UTF-8 encoding. Any file name returned by functions
1301 defined here must be in UTF-8 encoding, with only a few exceptions
1302 reserved for a couple of special cases. (Be sure to use
1303 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1304 as they can be much longer than MAX_PATH!)
1306 The UTF-8 encoded file names cannot be passed to system APIs, as
1307 Windows does not support that. Therefore, they are converted
1308 either to UTF-16 or to the ANSI codepage, depending on the value of
1309 w32-unicode-filenames, before calling any system APIs or CRT library
1310 functions. The default value of that variable is determined by the
1311 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1312 user can change that default (although I don't see why would she
1315 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1316 filename_from_utf16, and filename_from_ansi, are the workhorses of
1317 these conversions. They rely on Windows native APIs
1318 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1319 functions from coding.c here, because they allocate memory, which
1320 is a bad idea on the level of libc, which is what the functions
1321 here emulate. (If you worry about performance due to constant
1322 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1323 it was measured to take only a few microseconds on a not-so-fast
1324 machine, and second, that's exactly what the ANSI APIs we used
1325 before do anyway, because they are just thin wrappers around the
1328 The variables file-name-coding-system and default-file-name-coding-system
1329 still exist, but are actually used only when a file name needs to
1330 be converted to the ANSI codepage. This happens all the time when
1331 w32-unicode-filenames is nil, but can also happen from time to time
1332 when it is t. Otherwise, these variables have no effect on file-name
1333 encoding when w32-unicode-filenames is t; this is similar to
1334 selection-coding-system.
1336 This arrangement works very well, but it has a few gotchas:
1338 . Lisp code that encodes or decodes file names manually should
1339 normally use 'utf-8' as the coding-system on Windows,
1340 disregarding file-name-coding-system. This is a somewhat
1341 unpleasant consequence, but it cannot be avoided. Fortunately,
1342 very few Lisp packages need to do that.
1344 More generally, passing to library functions (e.g., fopen or
1345 opendir) file names already encoded in the ANSI codepage is
1346 explictly *verboten*, as all those functions, as shadowed and
1347 emulated here, assume they will receive UTF-8 encoded file names.
1349 For the same reasons, no CRT function or Win32 API can be called
1350 directly in Emacs sources, without either converting the file
1351 name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
1352 through some shadowing function defined here.
1354 . File names passed to external libraries, like the image libraries
1355 and GnuTLS, need special handling. These libraries generally
1356 don't support UTF-16 or UTF-8 file names, so they must get file
1357 names encoded in the ANSI codepage. To facilitate using these
1358 libraries with file names that are not encodable in the ANSI
1359 codepage, use the function ansi_encode_filename, which will try
1360 to use the short 8+3 alias of a file name if that file name is
1361 not encodable in the ANSI codepage. See image.c and gnutls.c for
1362 examples of how this should be done.
1364 . Running subprocesses in non-ASCII directories and with non-ASCII
1365 file arguments is limited to the current codepage (even though
1366 Emacs is perfectly capable of finding an executable program file
1367 even in a directory whose name cannot be encoded in the curreent
1368 codepage). This is because the command-line arguments are
1369 encoded _before_ they get to the w32-specific level, and the
1370 encoding is not known in advance (it doesn't have to be the
1371 current ANSI codepage), so w32proc.c functions cannot re-encode
1372 them in UTF-16. This should be fixed, but will also require
1373 changes in cmdproxy. The current limitation is not terribly bad
1374 anyway, since very few, if any, Windows console programs that are
1375 likely to be invoked by Emacs support UTF-16 encoded command
1378 . For similar reasons, server.el and emacsclient are also limited
1379 to the current ANSI codepage for now.
1385 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1386 codepage defined by file-name-coding-system. */
1388 /* Current codepage for encoding file names. */
1389 static int file_name_codepage
;
1391 /* Produce a Windows ANSI codepage suitable for encoding file names.
1392 Return the information about that codepage in CP_INFO. */
1394 codepage_for_filenames (CPINFO
*cp_info
)
1396 /* A simple cache to avoid calling GetCPInfo every time we need to
1397 encode/decode a file name. The file-name encoding is not
1398 supposed to be changed too frequently, if ever. */
1399 static Lisp_Object last_file_name_encoding
;
1401 Lisp_Object current_encoding
;
1403 current_encoding
= Vfile_name_coding_system
;
1404 if (NILP (current_encoding
))
1405 current_encoding
= Vdefault_file_name_coding_system
;
1407 if (!EQ (last_file_name_encoding
, current_encoding
))
1409 /* Default to the current ANSI codepage. */
1410 file_name_codepage
= w32_ansi_code_page
;
1412 if (NILP (current_encoding
))
1414 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1415 char *cp
= NULL
, *end
;
1418 if (strncmp (cpname
, "cp", 2) == 0)
1420 else if (strncmp (cpname
, "windows-", 8) == 0)
1426 cpnum
= strtol (cp
, &end
, 10);
1427 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1428 file_name_codepage
= cpnum
;
1432 if (!file_name_codepage
)
1433 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1435 if (!GetCPInfo (file_name_codepage
, &cp
))
1437 file_name_codepage
= CP_ACP
;
1438 if (!GetCPInfo (file_name_codepage
, &cp
))
1445 return file_name_codepage
;
1449 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1451 int result
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1456 DWORD err
= GetLastError ();
1460 case ERROR_INVALID_FLAGS
:
1461 case ERROR_INVALID_PARAMETER
:
1464 case ERROR_INSUFFICIENT_BUFFER
:
1465 case ERROR_NO_UNICODE_TRANSLATION
:
1476 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1478 int result
= WideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1479 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1483 DWORD err
= GetLastError ();
1487 case ERROR_INVALID_FLAGS
:
1488 case ERROR_INVALID_PARAMETER
:
1491 case ERROR_INSUFFICIENT_BUFFER
:
1492 case ERROR_NO_UNICODE_TRANSLATION
:
1503 filename_to_ansi (const char *fn_in
, char *fn_out
)
1505 wchar_t fn_utf16
[MAX_PATH
];
1507 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1510 int codepage
= codepage_for_filenames (NULL
);
1512 result
= WideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1513 fn_out
, MAX_PATH
, NULL
, NULL
);
1516 DWORD err
= GetLastError ();
1520 case ERROR_INVALID_FLAGS
:
1521 case ERROR_INVALID_PARAMETER
:
1524 case ERROR_INSUFFICIENT_BUFFER
:
1525 case ERROR_NO_UNICODE_TRANSLATION
:
1538 filename_from_ansi (const char *fn_in
, char *fn_out
)
1540 wchar_t fn_utf16
[MAX_PATH
];
1541 int codepage
= codepage_for_filenames (NULL
);
1542 int result
= MultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1543 fn_utf16
, MAX_PATH
);
1547 DWORD err
= GetLastError ();
1551 case ERROR_INVALID_FLAGS
:
1552 case ERROR_INVALID_PARAMETER
:
1555 case ERROR_INSUFFICIENT_BUFFER
:
1556 case ERROR_NO_UNICODE_TRANSLATION
:
1563 return filename_from_utf16 (fn_utf16
, fn_out
);
1568 /* The directory where we started, in UTF-8. */
1569 static char startup_dir
[MAX_UTF8_PATH
];
1571 /* Get the current working directory. */
1573 getcwd (char *dir
, int dirsize
)
1580 if (dirsize
<= strlen (startup_dir
))
1586 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1590 /* Emacs doesn't actually change directory itself, it stays in the
1591 same directory where it was started. */
1592 strcpy (dir
, startup_dir
);
1597 /* Emulate getloadavg. */
1599 struct load_sample
{
1606 /* Number of processors on this machine. */
1607 static unsigned num_of_processors
;
1609 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1610 static struct load_sample samples
[16*60];
1611 static int first_idx
= -1, last_idx
= -1;
1612 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1617 int next_idx
= from
+ 1;
1619 if (next_idx
>= max_idx
)
1628 int prev_idx
= from
- 1;
1631 prev_idx
= max_idx
- 1;
1637 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1639 SYSTEM_INFO sysinfo
;
1640 FILETIME ft_idle
, ft_user
, ft_kernel
;
1642 /* Initialize the number of processors on this machine. */
1643 if (num_of_processors
<= 0)
1645 get_native_system_info (&sysinfo
);
1646 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1647 if (num_of_processors
<= 0)
1649 GetSystemInfo (&sysinfo
);
1650 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1652 if (num_of_processors
<= 0)
1653 num_of_processors
= 1;
1656 /* TODO: Take into account threads that are ready to run, by
1657 sampling the "\System\Processor Queue Length" performance
1658 counter. The code below accounts only for threads that are
1659 actually running. */
1661 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1663 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1665 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1666 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1667 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1668 *idle
= uidle
.QuadPart
;
1669 *kernel
= ukernel
.QuadPart
;
1670 *user
= uuser
.QuadPart
;
1680 /* Produce the load average for a given time interval, using the
1681 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1682 1-minute, 5-minute, or 15-minute average, respectively. */
1686 double retval
= -1.0;
1689 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1690 time_t now
= samples
[last_idx
].sample_time
;
1692 if (first_idx
!= last_idx
)
1694 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1696 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1697 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1700 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1701 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1702 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1704 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1707 if (idx
== first_idx
)
1716 getloadavg (double loadavg
[], int nelem
)
1719 ULONGLONG idle
, kernel
, user
;
1720 time_t now
= time (NULL
);
1722 /* Store another sample. We ignore samples that are less than 1 sec
1724 if (difftime (now
, samples
[last_idx
].sample_time
) >= 1.0 - 2*DBL_EPSILON
*now
)
1726 sample_system_load (&idle
, &kernel
, &user
);
1727 last_idx
= buf_next (last_idx
);
1728 samples
[last_idx
].sample_time
= now
;
1729 samples
[last_idx
].idle
= idle
;
1730 samples
[last_idx
].kernel
= kernel
;
1731 samples
[last_idx
].user
= user
;
1732 /* If the buffer has more that 15 min worth of samples, discard
1734 if (first_idx
== -1)
1735 first_idx
= last_idx
;
1736 while (first_idx
!= last_idx
1737 && (difftime (now
, samples
[first_idx
].sample_time
)
1738 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1739 first_idx
= buf_next (first_idx
);
1742 for (elem
= 0; elem
< nelem
; elem
++)
1744 double avg
= getavg (elem
);
1748 loadavg
[elem
] = avg
;
1754 /* Emulate getpwuid, getpwnam and others. */
1756 #define PASSWD_FIELD_SIZE 256
1758 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1759 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1760 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1761 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1762 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1764 static struct passwd dflt_passwd
=
1776 static char dflt_group_name
[GNLEN
+1];
1778 static struct group dflt_group
=
1780 /* When group information is not available, we return this as the
1781 group for all files. */
1789 return dflt_passwd
.pw_uid
;
1795 /* I could imagine arguing for checking to see whether the user is
1796 in the Administrators group and returning a UID of 0 for that
1797 case, but I don't know how wise that would be in the long run. */
1804 return dflt_passwd
.pw_gid
;
1814 getpwuid (unsigned uid
)
1816 if (uid
== dflt_passwd
.pw_uid
)
1817 return &dflt_passwd
;
1822 getgrgid (gid_t gid
)
1828 getpwnam (char *name
)
1832 pw
= getpwuid (getuid ());
1836 if (xstrcasecmp (name
, pw
->pw_name
))
1843 init_user_info (void)
1845 /* Find the user's real name by opening the process token and
1846 looking up the name associated with the user-sid in that token.
1848 Use the relative portion of the identifier authority value from
1849 the user-sid as the user id value (same for group id using the
1850 primary group sid from the process token). */
1852 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1853 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1854 DWORD glength
= sizeof (gname
);
1855 HANDLE token
= NULL
;
1856 SID_NAME_USE user_type
;
1857 unsigned char *buf
= NULL
;
1859 TOKEN_USER user_token
;
1860 TOKEN_PRIMARY_GROUP group_token
;
1863 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1866 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1867 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1869 buf
= xmalloc (blen
);
1870 result
= get_token_information (token
, TokenUser
,
1871 (LPVOID
)buf
, blen
, &needed
);
1874 memcpy (&user_token
, buf
, sizeof (user_token
));
1875 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1877 domain
, &dlength
, &user_type
);
1885 strcpy (dflt_passwd
.pw_name
, uname
);
1886 /* Determine a reasonable uid value. */
1887 if (xstrcasecmp ("administrator", uname
) == 0)
1889 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
1890 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
1894 /* Use the last sub-authority value of the RID, the relative
1895 portion of the SID, as user/group ID. */
1896 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
1898 /* Get group id and name. */
1899 result
= get_token_information (token
, TokenPrimaryGroup
,
1900 (LPVOID
)buf
, blen
, &needed
);
1901 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1903 buf
= xrealloc (buf
, blen
= needed
);
1904 result
= get_token_information (token
, TokenPrimaryGroup
,
1905 (LPVOID
)buf
, blen
, &needed
);
1909 memcpy (&group_token
, buf
, sizeof (group_token
));
1910 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
1911 dlength
= sizeof (domain
);
1912 /* If we can get at the real Primary Group name, use that.
1913 Otherwise, the default group name was already set to
1914 "None" in globals_of_w32. */
1915 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
1916 gname
, &glength
, NULL
, &dlength
,
1918 strcpy (dflt_group_name
, gname
);
1921 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1924 /* If security calls are not supported (presumably because we
1925 are running under Windows 9X), fallback to this: */
1926 else if (GetUserName (uname
, &ulength
))
1928 strcpy (dflt_passwd
.pw_name
, uname
);
1929 if (xstrcasecmp ("administrator", uname
) == 0)
1930 dflt_passwd
.pw_uid
= 0;
1932 dflt_passwd
.pw_uid
= 123;
1933 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1937 strcpy (dflt_passwd
.pw_name
, "unknown");
1938 dflt_passwd
.pw_uid
= 123;
1939 dflt_passwd
.pw_gid
= 123;
1941 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
1943 /* Set dir and shell from environment variables. */
1944 if (w32_unicode_filenames
)
1946 wchar_t *home
= _wgetenv (L
"HOME");
1947 wchar_t *shell
= _wgetenv (L
"SHELL");
1949 /* Ensure HOME and SHELL are defined. */
1954 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
1955 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
1959 char *home
= getenv ("HOME");
1960 char *shell
= getenv ("SHELL");
1966 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
1967 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
1972 CloseHandle (token
);
1978 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
1979 return ((rand () << 15) | rand ());
1988 /* Return the maximum length in bytes of a multibyte character
1989 sequence encoded in the current ANSI codepage. This is required to
1990 correctly walk the encoded file names one character at a time. */
1992 max_filename_mbslen (void)
1996 codepage_for_filenames (&cp_info
);
1997 return cp_info
.MaxCharSize
;
2000 /* Normalize filename by converting in-place all of its path
2001 separators to the separator specified by PATH_SEP. */
2004 normalize_filename (register char *fp
, char path_sep
)
2008 /* Always lower-case drive letters a-z, even if the filesystem
2009 preserves case in filenames.
2010 This is so filenames can be compared by string comparison
2011 functions that are case-sensitive. Even case-preserving filesystems
2012 do not distinguish case in drive letters. */
2015 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2023 if (*fp
== '/' || *fp
== '\\')
2029 /* Destructively turn backslashes into slashes. */
2031 dostounix_filename (register char *p
)
2033 normalize_filename (p
, '/');
2036 /* Destructively turn slashes into backslashes. */
2038 unixtodos_filename (register char *p
)
2040 normalize_filename (p
, '\\');
2043 /* Remove all CR's that are followed by a LF.
2044 (From msdos.c...probably should figure out a way to share it,
2045 although this code isn't going to ever change.) */
2047 crlf_to_lf (register int n
, register unsigned char *buf
)
2049 unsigned char *np
= buf
;
2050 unsigned char *startp
= buf
;
2051 unsigned char *endp
= buf
+ n
;
2055 while (buf
< endp
- 1)
2059 if (*(++buf
) != 0x0a)
2070 /* Parse the root part of file name, if present. Return length and
2071 optionally store pointer to char after root. */
2073 parse_root (const char * name
, const char ** pPath
)
2075 const char * start
= name
;
2080 /* find the root name of the volume if given */
2081 if (isalpha (name
[0]) && name
[1] == ':')
2083 /* skip past drive specifier */
2085 if (IS_DIRECTORY_SEP (name
[0]))
2088 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2095 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2100 if (IS_DIRECTORY_SEP (name
[0]))
2107 return name
- start
;
2110 /* Get long base name for name; name is assumed to be absolute. */
2112 get_long_basename (char * name
, char * buf
, int size
)
2115 char fname_utf8
[MAX_UTF8_PATH
];
2119 /* Must be valid filename, no wild cards or other invalid characters. */
2120 if (strpbrk (name
, "*?|<>\""))
2123 if (w32_unicode_filenames
)
2125 wchar_t fname_utf16
[MAX_PATH
];
2126 WIN32_FIND_DATAW find_data_wide
;
2128 filename_to_utf16 (name
, fname_utf16
);
2129 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2130 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2131 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2135 char fname_ansi
[MAX_PATH
];
2136 WIN32_FIND_DATAA find_data_ansi
;
2138 filename_to_ansi (name
, fname_ansi
);
2139 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2140 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2141 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2144 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2145 memcpy (buf
, fname_utf8
, len
+ 1);
2149 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2150 FindClose (dir_handle
);
2155 /* Get long name for file, if possible (assumed to be absolute). */
2157 w32_get_long_filename (char * name
, char * buf
, int size
)
2162 char full
[ MAX_UTF8_PATH
];
2165 len
= strlen (name
);
2166 if (len
>= MAX_UTF8_PATH
)
2169 /* Use local copy for destructive modification. */
2170 memcpy (full
, name
, len
+1);
2171 unixtodos_filename (full
);
2173 /* Copy root part verbatim. */
2174 len
= parse_root (full
, (const char **)&p
);
2175 memcpy (o
, full
, len
);
2180 while (p
!= NULL
&& *p
)
2183 p
= strchr (q
, '\\');
2185 len
= get_long_basename (full
, o
, size
);
2208 w32_get_short_filename (char * name
, char * buf
, int size
)
2210 if (w32_unicode_filenames
)
2212 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2213 unsigned int retval
;
2215 filename_to_utf16 (name
, name_utf16
);
2216 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2217 if (retval
&& retval
< size
)
2218 filename_from_utf16 (short_name
, buf
);
2223 char name_ansi
[MAX_PATH
];
2225 filename_to_ansi (name
, name_ansi
);
2226 return GetShortPathNameA (name_ansi
, buf
, size
);
2230 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2231 MS-Windows ANSI codepage. If FILENAME includes characters not
2232 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2233 if it exists. This is needed because the w32 build wants to
2234 support file names outside of the system locale, but image
2235 libraries typically don't support wide (a.k.a. "Unicode") APIs
2236 required for that. */
2239 ansi_encode_filename (Lisp_Object filename
)
2241 Lisp_Object encoded_filename
;
2242 char fname
[MAX_PATH
];
2244 filename_to_ansi (SSDATA (filename
), fname
);
2245 if (_mbspbrk (fname
, "?"))
2247 char shortname
[MAX_PATH
];
2249 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2251 dostounix_filename (shortname
);
2252 encoded_filename
= build_string (shortname
);
2256 encoded_filename
= build_unibyte_string (fname
);
2257 return encoded_filename
;
2261 is_unc_volume (const char *filename
)
2263 const char *ptr
= filename
;
2265 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2268 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2274 /* Emulate the Posix unsetenv. */
2276 unsetenv (const char *name
)
2282 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2287 name_len
= strlen (name
);
2288 /* MS docs says an environment variable cannot be longer than 32K. */
2289 if (name_len
> 32767)
2294 /* It is safe to use 'alloca' with 32K size, since the stack is at
2295 least 2MB, and we set it to 8MB in the link command line. */
2296 var
= alloca (name_len
+ 2);
2297 strncpy (var
, name
, name_len
);
2298 var
[name_len
++] = '=';
2299 var
[name_len
] = '\0';
2300 return _putenv (var
);
2303 /* MS _putenv doesn't support removing a variable when the argument
2304 does not include the '=' character, so we fix that here. */
2306 sys_putenv (char *str
)
2308 const char *const name_end
= strchr (str
, '=');
2310 if (name_end
== NULL
)
2312 /* Remove the variable from the environment. */
2313 return unsetenv (str
);
2316 return _putenv (str
);
2319 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2322 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2325 HKEY hrootkey
= NULL
;
2328 /* Check both the current user and the local machine to see if
2329 we have any resources. */
2331 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2335 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2336 && (lpvalue
= xmalloc (cbData
)) != NULL
2337 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2339 RegCloseKey (hrootkey
);
2345 RegCloseKey (hrootkey
);
2348 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2352 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2353 && (lpvalue
= xmalloc (cbData
)) != NULL
2354 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2356 RegCloseKey (hrootkey
);
2362 RegCloseKey (hrootkey
);
2369 init_environment (char ** argv
)
2371 static const char * const tempdirs
[] = {
2372 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2377 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2379 /* Implementation note: This function explicitly works with ANSI
2380 file names, not with UTF-8 encoded file names. This is because
2381 this function pushes variables into the Emacs's environment, and
2382 the environment variables are always assumed to be in the
2383 locale-specific encoding. Do NOT call any functions that accept
2384 UTF-8 file names from this function! */
2386 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2387 temporary files and assume "/tmp" if $TMPDIR is unset, which
2388 will break on DOS/Windows. Refuse to work if we cannot find
2389 a directory, not even "c:/", usable for that purpose. */
2390 for (i
= 0; i
< imax
; i
++)
2392 const char *tmp
= tempdirs
[i
];
2395 tmp
= getenv (tmp
+ 1);
2396 /* Note that `access' can lie to us if the directory resides on a
2397 read-only filesystem, like CD-ROM or a write-protected floppy.
2398 The only way to be really sure is to actually create a file and
2399 see if it succeeds. But I think that's too much to ask. */
2401 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2402 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2404 char * var
= alloca (strlen (tmp
) + 8);
2405 sprintf (var
, "TMPDIR=%s", tmp
);
2406 _putenv (strdup (var
));
2413 Fcons (build_string ("no usable temporary directories found!!"),
2415 "While setting TMPDIR: ");
2417 /* Check for environment variables and use registry settings if they
2418 don't exist. Fallback on default values where applicable. */
2423 char locale_name
[32];
2424 char default_home
[MAX_PATH
];
2427 static const struct env_entry
2433 /* If the default value is NULL, we will use the value from the
2434 outside environment or the Registry, but will not push the
2435 variable into the Emacs environment if it is defined neither
2436 in the Registry nor in the outside environment. */
2438 {"PRELOAD_WINSOCK", NULL
},
2439 {"emacs_dir", "C:/emacs"},
2440 {"EMACSLOADPATH", NULL
},
2441 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2442 {"EMACSDATA", NULL
},
2443 {"EMACSPATH", NULL
},
2450 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2452 /* We need to copy dflt_envvars[] and work on the copy because we
2453 don't want the dumped Emacs to inherit the values of
2454 environment variables we saw during dumping (which could be on
2455 a different system). The defaults above must be left intact. */
2456 struct env_entry env_vars
[N_ENV_VARS
];
2458 for (i
= 0; i
< N_ENV_VARS
; i
++)
2459 env_vars
[i
] = dflt_envvars
[i
];
2461 /* For backwards compatibility, check if a .emacs file exists in C:/
2462 If not, then we can try to default to the appdata directory under the
2463 user's profile, which is more likely to be writable. */
2464 if (sys_access ("C:/.emacs", F_OK
) != 0)
2466 HRESULT profile_result
;
2467 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2468 of Windows 95 and NT4 that have not been updated to include
2470 ShGetFolderPath_fn get_folder_path
;
2471 get_folder_path
= (ShGetFolderPath_fn
)
2472 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2474 if (get_folder_path
!= NULL
)
2476 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2479 /* If we can't get the appdata dir, revert to old behavior. */
2480 if (profile_result
== S_OK
)
2482 env_vars
[0].def_value
= default_home
;
2488 /* Get default locale info and use it for LANG. */
2489 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2490 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2491 locale_name
, sizeof (locale_name
)))
2493 for (i
= 0; i
< N_ENV_VARS
; i
++)
2495 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2497 env_vars
[i
].def_value
= locale_name
;
2503 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2505 /* Treat emacs_dir specially: set it unconditionally based on our
2509 char modname
[MAX_PATH
];
2511 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
2513 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2517 if ((p
= _mbsrchr (modname
, '\\'))
2518 /* From bin means installed Emacs, from src means uninstalled. */
2519 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2521 char buf
[SET_ENV_BUF_SIZE
];
2522 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2525 for (p
= modname
; *p
; p
= CharNext (p
))
2526 if (*p
== '\\') *p
= '/';
2528 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2529 _putenv (strdup (buf
));
2530 /* If we are running from the Posix-like build tree, define
2531 SHELL to point to our own cmdproxy. The loop below will
2532 then disregard PATH_EXEC and the default value. */
2533 if (within_build_tree
)
2535 _snprintf (buf
, sizeof (buf
) - 1,
2536 "SHELL=%s/nt/cmdproxy.exe", modname
);
2537 _putenv (strdup (buf
));
2542 for (i
= 0; i
< N_ENV_VARS
; i
++)
2544 if (!getenv (env_vars
[i
].name
))
2547 char bufc
[SET_ENV_BUF_SIZE
];
2549 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2550 /* Also ignore empty environment variables. */
2555 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2557 /* Look for cmdproxy.exe in every directory in
2558 PATH_EXEC. FIXME: This does not find cmdproxy
2559 in nt/ when we run uninstalled. */
2560 char fname
[MAX_PATH
];
2561 const char *pstart
= PATH_EXEC
, *pend
;
2564 pend
= _mbschr (pstart
, ';');
2566 pend
= pstart
+ strlen (pstart
);
2567 /* Be defensive against series of ;;; characters. */
2570 strncpy (fname
, pstart
, pend
- pstart
);
2571 fname
[pend
- pstart
] = '/';
2572 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2573 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2575 if (sys_access (bufc
, F_OK
) == 0)
2588 /* If not found in any directory, use the
2589 default as the last resort. */
2590 lpval
= env_vars
[i
].def_value
;
2591 dwType
= REG_EXPAND_SZ
;
2597 lpval
= env_vars
[i
].def_value
;
2598 dwType
= REG_EXPAND_SZ
;
2600 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2601 Vdelayed_warnings_list
2602 = Fcons (listn (CONSTYPE_HEAP
, 2,
2603 intern ("initialization"),
2604 build_string ("Setting HOME to C:\\ by default is deprecated")),
2605 Vdelayed_warnings_list
);
2610 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2612 if (dwType
== REG_EXPAND_SZ
)
2613 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2614 else if (dwType
== REG_SZ
)
2615 strcpy (buf1
, lpval
);
2616 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2618 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2620 _putenv (strdup (buf2
));
2630 /* Rebuild system configuration to reflect invoking system. */
2631 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2633 /* Another special case: on NT, the PATH variable is actually named
2634 "Path" although cmd.exe (perhaps NT itself) arranges for
2635 environment variable lookup and setting to be case insensitive.
2636 However, Emacs assumes a fully case sensitive environment, so we
2637 need to change "Path" to "PATH" to match the expectations of
2638 various elisp packages. We do this by the sneaky method of
2639 modifying the string in the C runtime environ entry.
2641 The same applies to COMSPEC. */
2645 for (envp
= environ
; *envp
; envp
++)
2646 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2647 memcpy (*envp
, "PATH=", 5);
2648 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2649 memcpy (*envp
, "COMSPEC=", 8);
2652 /* Remember the initial working directory for getcwd. */
2653 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2654 Does it matter anywhere in Emacs? */
2655 if (w32_unicode_filenames
)
2657 wchar_t wstartup_dir
[MAX_PATH
];
2659 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2661 filename_from_utf16 (wstartup_dir
, startup_dir
);
2665 char astartup_dir
[MAX_PATH
];
2667 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2669 filename_from_ansi (astartup_dir
, startup_dir
);
2673 static char modname
[MAX_PATH
];
2675 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
2680 /* Determine if there is a middle mouse button, to allow parse_button
2681 to decide whether right mouse events should be mouse-2 or
2683 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2688 /* Called from expand-file-name when default-directory is not a string. */
2691 emacs_root_dir (void)
2693 static char root_dir
[MAX_UTF8_PATH
];
2696 p
= getenv ("emacs_dir");
2699 filename_from_ansi (p
, root_dir
);
2700 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2701 dostounix_filename (root_dir
);
2705 #include <sys/timeb.h>
2707 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2709 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2714 tv
->tv_sec
= tb
.time
;
2715 tv
->tv_usec
= tb
.millitm
* 1000L;
2716 /* Implementation note: _ftime sometimes doesn't update the dstflag
2717 according to the new timezone when the system timezone is
2718 changed. We could fix that by using GetSystemTime and
2719 GetTimeZoneInformation, but that doesn't seem necessary, since
2720 Emacs always calls gettimeofday with the 2nd argument NULL (see
2721 current_emacs_time). */
2724 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2725 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2730 /* Emulate fdutimens. */
2732 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2733 TIMESPEC[0] and TIMESPEC[1], respectively.
2734 FD must be either negative -- in which case it is ignored --
2735 or a file descriptor that is open on FILE.
2736 If FD is nonnegative, then FILE can be NULL, which means
2737 use just futimes instead of utimes.
2738 If TIMESPEC is null, FAIL.
2739 Return 0 on success, -1 (setting errno) on failure. */
2742 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2749 if (fd
< 0 && !file
)
2754 /* _futime's prototype defines 2nd arg as having the type 'struct
2755 _utimbuf', while utime needs to accept 'struct utimbuf' for
2756 compatibility with Posix. So we need to use 2 different (but
2757 equivalent) types to avoid compiler warnings, sigh. */
2760 struct _utimbuf _ut
;
2762 _ut
.actime
= timespec
[0].tv_sec
;
2763 _ut
.modtime
= timespec
[1].tv_sec
;
2764 return _futime (fd
, &_ut
);
2770 ut
.actime
= timespec
[0].tv_sec
;
2771 ut
.modtime
= timespec
[1].tv_sec
;
2772 /* Call 'utime', which is implemented below, not the MS library
2773 function, which fails on directories. */
2774 return utime (file
, &ut
);
2779 /* ------------------------------------------------------------------------- */
2780 /* IO support and wrapper functions for the Windows API. */
2781 /* ------------------------------------------------------------------------- */
2783 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2784 on network directories, so we handle that case here.
2785 (Ulrich Leodolter, 1/11/95). */
2787 sys_ctime (const time_t *t
)
2789 char *str
= (char *) ctime (t
);
2790 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2793 /* Emulate sleep...we could have done this with a define, but that
2794 would necessitate including windows.h in the files that used it.
2795 This is much easier. */
2797 sys_sleep (int seconds
)
2799 Sleep (seconds
* 1000);
2802 /* Internal MSVC functions for low-level descriptor munging */
2803 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2804 extern int __cdecl
_free_osfhnd (int fd
);
2806 /* parallel array of private info on file handles */
2807 filedesc fd_info
[ MAXDESC
];
2809 typedef struct volume_info_data
{
2810 struct volume_info_data
* next
;
2812 /* time when info was obtained */
2815 /* actual volume info */
2824 /* Global referenced by various functions. */
2825 static volume_info_data volume_info
;
2827 /* Vector to indicate which drives are local and fixed (for which cached
2828 data never expires). */
2829 static BOOL fixed_drives
[26];
2831 /* Consider cached volume information to be stale if older than 10s,
2832 at least for non-local drives. Info for fixed drives is never stale. */
2833 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2834 #define VOLINFO_STILL_VALID( root_dir, info ) \
2835 ( ( isalpha (root_dir[0]) && \
2836 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2837 || GetTickCount () - info->timestamp < 10000 )
2839 /* Cache support functions. */
2841 /* Simple linked list with linear search is sufficient. */
2842 static volume_info_data
*volume_cache
= NULL
;
2844 static volume_info_data
*
2845 lookup_volume_info (char * root_dir
)
2847 volume_info_data
* info
;
2849 for (info
= volume_cache
; info
; info
= info
->next
)
2850 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2856 add_volume_info (char * root_dir
, volume_info_data
* info
)
2858 info
->root_dir
= xstrdup (root_dir
);
2859 unixtodos_filename (info
->root_dir
);
2860 info
->next
= volume_cache
;
2861 volume_cache
= info
;
2865 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2866 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2867 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2868 static volume_info_data
*
2869 GetCachedVolumeInformation (char * root_dir
)
2871 volume_info_data
* info
;
2872 char default_root
[ MAX_UTF8_PATH
];
2873 char name
[MAX_PATH
+1];
2874 char type
[MAX_PATH
+1];
2876 /* NULL for root_dir means use root from current directory. */
2877 if (root_dir
== NULL
)
2879 if (w32_unicode_filenames
)
2881 wchar_t curdirw
[MAX_PATH
];
2883 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
2885 filename_from_utf16 (curdirw
, default_root
);
2889 char curdira
[MAX_PATH
];
2891 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
2893 filename_from_ansi (curdira
, default_root
);
2895 parse_root (default_root
, (const char **)&root_dir
);
2897 root_dir
= default_root
;
2900 /* Local fixed drives can be cached permanently. Removable drives
2901 cannot be cached permanently, since the volume name and serial
2902 number (if nothing else) can change. Remote drives should be
2903 treated as if they are removable, since there is no sure way to
2904 tell whether they are or not. Also, the UNC association of drive
2905 letters mapped to remote volumes can be changed at any time (even
2906 by other processes) without notice.
2908 As a compromise, so we can benefit from caching info for remote
2909 volumes, we use a simple expiry mechanism to invalidate cache
2910 entries that are more than ten seconds old. */
2913 /* No point doing this, because WNetGetConnection is even slower than
2914 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2915 GetDriveType is about the only call of this type which does not
2916 involve network access, and so is extremely quick). */
2918 /* Map drive letter to UNC if remote. */
2919 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2921 char remote_name
[ 256 ];
2922 char drive
[3] = { root_dir
[0], ':' };
2924 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2926 /* do something */ ;
2930 info
= lookup_volume_info (root_dir
);
2932 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2938 /* Info is not cached, or is stale. */
2939 if (w32_unicode_filenames
)
2941 wchar_t root_w
[MAX_PATH
];
2942 wchar_t name_w
[MAX_PATH
+1];
2943 wchar_t type_w
[MAX_PATH
+1];
2945 filename_to_utf16 (root_dir
, root_w
);
2946 if (!GetVolumeInformationW (root_w
,
2947 name_w
, sizeof (name_w
),
2951 type_w
, sizeof (type_w
)))
2953 /* Hmm... not really 100% correct, as these 2 are not file
2955 filename_from_utf16 (name_w
, name
);
2956 filename_from_utf16 (type_w
, type
);
2960 char root_a
[MAX_PATH
];
2961 char name_a
[MAX_PATH
+1];
2962 char type_a
[MAX_PATH
+1];
2964 filename_to_ansi (root_dir
, root_a
);
2965 if (!GetVolumeInformationA (root_a
,
2966 name_a
, sizeof (name_a
),
2970 type_a
, sizeof (type_a
)))
2972 filename_from_ansi (name_a
, name
);
2973 filename_from_ansi (type_a
, type
);
2976 /* Cache the volume information for future use, overwriting existing
2977 entry if present. */
2980 info
= xmalloc (sizeof (volume_info_data
));
2981 add_volume_info (root_dir
, info
);
2989 info
->name
= xstrdup (name
);
2990 unixtodos_filename (info
->name
);
2991 info
->serialnum
= serialnum
;
2992 info
->maxcomp
= maxcomp
;
2993 info
->flags
= flags
;
2994 info
->type
= xstrdup (type
);
2995 info
->timestamp
= GetTickCount ();
3001 /* Get information on the volume where NAME is held; set path pointer to
3002 start of pathname in NAME (past UNC header\volume header if present),
3003 if pPath is non-NULL.
3005 Note: if NAME includes symlinks, the information is for the volume
3006 of the symlink, not of its target. That's because, even though
3007 GetVolumeInformation returns information about the symlink target
3008 of its argument, we only pass the root directory to
3009 GetVolumeInformation, not the full NAME. */
3011 get_volume_info (const char * name
, const char ** pPath
)
3013 char temp
[MAX_UTF8_PATH
];
3014 char *rootname
= NULL
; /* default to current volume */
3015 volume_info_data
* info
;
3016 int root_len
= parse_root (name
, pPath
);
3021 /* Copy the root name of the volume, if given. */
3024 strncpy (temp
, name
, root_len
);
3025 temp
[root_len
] = '\0';
3026 unixtodos_filename (temp
);
3030 info
= GetCachedVolumeInformation (rootname
);
3033 /* Set global referenced by other functions. */
3034 volume_info
= *info
;
3040 /* Determine if volume is FAT format (ie. only supports short 8.3
3041 names); also set path pointer to start of pathname in name, if
3042 pPath is non-NULL. */
3044 is_fat_volume (const char * name
, const char ** pPath
)
3046 if (get_volume_info (name
, pPath
))
3047 return (volume_info
.maxcomp
== 12);
3051 /* Convert all slashes in a filename to backslashes, and map filename
3052 to a valid 8.3 name if necessary. The result is a pointer to a
3053 static buffer, so CAVEAT EMPTOR! */
3055 map_w32_filename (const char * name
, const char ** pPath
)
3057 static char shortname
[MAX_UTF8_PATH
];
3058 char * str
= shortname
;
3061 const char * save_name
= name
;
3063 if (strlen (name
) >= sizeof (shortname
))
3065 /* Return a filename which will cause callers to fail. */
3066 strcpy (shortname
, "?");
3070 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3072 register int left
= 8; /* maximum number of chars in part */
3073 register int extn
= 0; /* extension added? */
3074 register int dots
= 2; /* maximum number of dots allowed */
3077 *str
++ = *name
++; /* skip past UNC header */
3079 while ((c
= *name
++))
3086 *str
++ = (c
== ':' ? ':' : '\\');
3087 extn
= 0; /* reset extension flags */
3088 dots
= 2; /* max 2 dots */
3089 left
= 8; /* max length 8 for main part */
3094 /* Convert path components of the form .xxx to _xxx,
3095 but leave . and .. as they are. This allows .emacs
3096 to be read as _emacs, for example. */
3100 IS_DIRECTORY_SEP (*name
))
3115 extn
= 1; /* we've got an extension */
3116 left
= 3; /* 3 chars in extension */
3120 /* any embedded dots after the first are converted to _ */
3125 case '#': /* don't lose these, they're important */
3127 str
[-1] = c
; /* replace last character of part */
3130 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3132 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3134 dots
= 0; /* started a path component */
3143 strcpy (shortname
, name
);
3144 unixtodos_filename (shortname
);
3148 *pPath
= shortname
+ (path
- save_name
);
3154 is_exec (const char * name
)
3156 char * p
= strrchr (name
, '.');
3159 && (xstrcasecmp (p
, ".exe") == 0 ||
3160 xstrcasecmp (p
, ".com") == 0 ||
3161 xstrcasecmp (p
, ".bat") == 0 ||
3162 xstrcasecmp (p
, ".cmd") == 0));
3165 /* Emulate the Unix directory procedures opendir, closedir, and
3166 readdir. We rename them to sys_* names because some versions of
3167 MinGW startup code call opendir and readdir to glob wildcards, and
3168 the code that calls them doesn't grok UTF-8 encoded file names we
3169 produce in dirent->d_name[]. */
3171 struct dirent dir_static
; /* simulated directory contents */
3172 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3173 static int dir_is_fat
;
3174 static char dir_pathname
[MAX_UTF8_PATH
];
3175 static WIN32_FIND_DATAW dir_find_data_w
;
3176 static WIN32_FIND_DATAA dir_find_data_a
;
3177 #define DIR_FIND_DATA_W 1
3178 #define DIR_FIND_DATA_A 2
3179 static int last_dir_find_data
= -1;
3181 /* Support shares on a network resource as subdirectories of a read-only
3183 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3184 static HANDLE
open_unc_volume (const char *);
3185 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3186 static void close_unc_volume (HANDLE
);
3189 sys_opendir (const char *filename
)
3193 /* Opening is done by FindFirstFile. However, a read is inherent to
3194 this operation, so we defer the open until read time. */
3196 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3198 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3201 /* Note: We don't support traversal of UNC volumes via symlinks.
3202 Doing so would mean punishing 99.99% of use cases by resolving
3203 all the possible symlinks in FILENAME, recursively. */
3204 if (is_unc_volume (filename
))
3206 wnet_enum_handle
= open_unc_volume (filename
);
3207 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3211 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3218 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3219 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3220 /* Note: We don't support symlinks to file names on FAT volumes.
3221 Doing so would mean punishing 99.99% of use cases by resolving
3222 all the possible symlinks in FILENAME, recursively. */
3223 dir_is_fat
= is_fat_volume (filename
, NULL
);
3229 sys_closedir (DIR *dirp
)
3231 /* If we have a find-handle open, close it. */
3232 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3234 FindClose (dir_find_handle
);
3235 dir_find_handle
= INVALID_HANDLE_VALUE
;
3237 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3239 close_unc_volume (wnet_enum_handle
);
3240 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3242 xfree ((char *) dirp
);
3246 sys_readdir (DIR *dirp
)
3248 int downcase
= !NILP (Vw32_downcase_file_names
);
3250 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3252 if (!read_unc_volume (wnet_enum_handle
,
3253 dir_find_data_w
.cFileName
,
3254 dir_find_data_a
.cFileName
,
3258 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3259 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3261 char filename
[MAX_UTF8_PATH
+ 2];
3264 strcpy (filename
, dir_pathname
);
3265 ln
= strlen (filename
) - 1;
3266 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3267 strcat (filename
, "\\");
3268 strcat (filename
, "*");
3270 /* Note: No need to resolve symlinks in FILENAME, because
3271 FindFirst opens the directory that is the target of a
3273 if (w32_unicode_filenames
)
3275 wchar_t fnw
[MAX_PATH
];
3277 filename_to_utf16 (filename
, fnw
);
3278 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3284 filename_to_ansi (filename
, fna
);
3285 /* If FILENAME is not representable by the current ANSI
3286 codepage, we don't want FindFirstFileA to interpret the
3287 '?' characters as a wildcard. */
3288 if (_mbspbrk (fna
, "?"))
3289 dir_find_handle
= INVALID_HANDLE_VALUE
;
3291 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3294 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3297 else if (w32_unicode_filenames
)
3299 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3304 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3308 /* Emacs never uses this value, so don't bother making it match
3309 value returned by stat(). */
3310 dir_static
.d_ino
= 1;
3312 if (w32_unicode_filenames
)
3314 if (downcase
|| dir_is_fat
)
3316 wchar_t tem
[MAX_PATH
];
3318 wcscpy (tem
, dir_find_data_w
.cFileName
);
3320 filename_from_utf16 (tem
, dir_static
.d_name
);
3323 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3324 last_dir_find_data
= DIR_FIND_DATA_W
;
3330 /* If the file name in cFileName[] includes `?' characters, it
3331 means the original file name used characters that cannot be
3332 represented by the current ANSI codepage. To avoid total
3333 lossage, retrieve the short 8+3 alias of the long file
3335 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3337 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3338 /* 8+3 aliases are returned in all caps, which could break
3339 various alists that look at filenames' extensions. */
3342 else if (downcase
|| dir_is_fat
)
3343 strcpy (tem
, dir_find_data_a
.cFileName
);
3345 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3346 if (downcase
|| dir_is_fat
)
3349 filename_from_ansi (tem
, dir_static
.d_name
);
3351 last_dir_find_data
= DIR_FIND_DATA_A
;
3354 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3355 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3356 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3362 open_unc_volume (const char *path
)
3364 const char *fn
= map_w32_filename (path
, NULL
);
3368 if (w32_unicode_filenames
)
3371 wchar_t fnw
[MAX_PATH
];
3373 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3374 nrw
.dwType
= RESOURCETYPE_DISK
;
3375 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3376 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3377 nrw
.lpLocalName
= NULL
;
3378 filename_to_utf16 (fn
, fnw
);
3379 nrw
.lpRemoteName
= fnw
;
3380 nrw
.lpComment
= NULL
;
3381 nrw
.lpProvider
= NULL
;
3383 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3384 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3391 nra
.dwScope
= RESOURCE_GLOBALNET
;
3392 nra
.dwType
= RESOURCETYPE_DISK
;
3393 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3394 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3395 nra
.lpLocalName
= NULL
;
3396 filename_to_ansi (fn
, fna
);
3397 nra
.lpRemoteName
= fna
;
3398 nra
.lpComment
= NULL
;
3399 nra
.lpProvider
= NULL
;
3401 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3402 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3404 if (result
== NO_ERROR
)
3407 return INVALID_HANDLE_VALUE
;
3411 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3416 DWORD bufsize
= 512;
3420 if (w32_unicode_filenames
)
3425 buffer
= alloca (bufsize
);
3426 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3427 if (result
!= NO_ERROR
)
3429 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3430 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3432 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3434 wcsncpy (fname_w
, ptrw
, size
);
3439 int dbcs_p
= max_filename_mbslen () > 1;
3442 buffer
= alloca (bufsize
);
3443 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3444 if (result
!= NO_ERROR
)
3446 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3449 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3452 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3453 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3456 strncpy (fname_a
, ptra
, size
);
3464 close_unc_volume (HANDLE henum
)
3466 if (henum
!= INVALID_HANDLE_VALUE
)
3467 WNetCloseEnum (henum
);
3471 unc_volume_file_attributes (const char *path
)
3476 henum
= open_unc_volume (path
);
3477 if (henum
== INVALID_HANDLE_VALUE
)
3480 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3482 close_unc_volume (henum
);
3487 /* Ensure a network connection is authenticated. */
3489 logon_network_drive (const char *path
)
3491 char share
[MAX_UTF8_PATH
];
3498 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3499 drvtype
= DRIVE_REMOTE
;
3500 else if (path
[0] == '\0' || path
[1] != ':')
3501 drvtype
= GetDriveType (NULL
);
3508 drvtype
= GetDriveType (drive
);
3511 /* Only logon to networked drives. */
3512 if (drvtype
!= DRIVE_REMOTE
)
3516 strncpy (share
, path
, MAX_UTF8_PATH
);
3517 /* Truncate to just server and share name. */
3518 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3520 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3527 if (w32_unicode_filenames
)
3529 NETRESOURCEW resourcew
;
3530 wchar_t share_w
[MAX_PATH
];
3532 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3533 resourcew
.dwType
= RESOURCETYPE_DISK
;
3534 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3535 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3536 resourcew
.lpLocalName
= NULL
;
3537 filename_to_utf16 (share
, share_w
);
3538 resourcew
.lpRemoteName
= share_w
;
3539 resourcew
.lpProvider
= NULL
;
3541 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3545 NETRESOURCEA resourcea
;
3546 char share_a
[MAX_PATH
];
3548 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3549 resourcea
.dwType
= RESOURCETYPE_DISK
;
3550 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3551 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3552 resourcea
.lpLocalName
= NULL
;
3553 filename_to_ansi (share
, share_a
);
3554 resourcea
.lpRemoteName
= share_a
;
3555 resourcea
.lpProvider
= NULL
;
3557 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3563 case ERROR_ALREADY_ASSIGNED
:
3565 case ERROR_ACCESS_DENIED
:
3566 case ERROR_LOGON_FAILURE
:
3572 case ERROR_BAD_NET_NAME
:
3573 case ERROR_NO_NET_OR_BAD_PATH
:
3574 case ERROR_NO_NETWORK
:
3575 case ERROR_CANCELLED
:
3582 /* Emulate faccessat(2). */
3584 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3588 if (dirfd
!= AT_FDCWD
3589 && !(IS_DIRECTORY_SEP (path
[0])
3590 || IS_DEVICE_SEP (path
[1])))
3596 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3597 newer versions blow up when passed D_OK. */
3598 path
= map_w32_filename (path
, NULL
);
3599 /* If the last element of PATH is a symlink, we need to resolve it
3600 to get the attributes of its target file. Note: any symlinks in
3601 PATH elements other than the last one are transparently resolved
3602 by GetFileAttributes below. */
3603 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3604 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3605 path
= chase_symlinks (path
);
3607 if (w32_unicode_filenames
)
3609 wchar_t path_w
[MAX_PATH
];
3611 filename_to_utf16 (path
, path_w
);
3612 attributes
= GetFileAttributesW (path_w
);
3616 char path_a
[MAX_PATH
];
3618 filename_to_ansi (path
, path_a
);
3619 attributes
= GetFileAttributesA (path_a
);
3622 if (attributes
== -1)
3624 DWORD w32err
= GetLastError ();
3628 case ERROR_INVALID_NAME
:
3629 case ERROR_BAD_PATHNAME
:
3630 if (is_unc_volume (path
))
3632 attributes
= unc_volume_file_attributes (path
);
3633 if (attributes
== -1)
3641 case ERROR_FILE_NOT_FOUND
:
3642 case ERROR_BAD_NETPATH
:
3651 if ((mode
& X_OK
) != 0
3652 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3657 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3662 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3670 /* A version of 'access' to be used locally with file names in
3671 locale-specific encoding. Does not resolve symlinks and does not
3672 support file names on FAT12 and FAT16 volumes, but that's OK, since
3673 we only invoke this function for files inside the Emacs source or
3674 installation tree, on directories (so any symlinks should have the
3675 directory bit set), and on short file names such as "C:/.emacs". */
3677 sys_access (const char *fname
, int mode
)
3679 char fname_copy
[MAX_PATH
], *p
;
3682 strcpy (fname_copy
, fname
);
3683 /* Do the equivalent of unixtodos_filename. */
3684 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3688 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3690 DWORD w32err
= GetLastError ();
3694 case ERROR_INVALID_NAME
:
3695 case ERROR_BAD_PATHNAME
:
3696 case ERROR_FILE_NOT_FOUND
:
3697 case ERROR_BAD_NETPATH
:
3706 if ((mode
& X_OK
) != 0
3707 && !(is_exec (fname_copy
)
3708 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3713 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3718 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3726 /* Shadow some MSVC runtime functions to map requests for long filenames
3727 to reasonable short names if necessary. This was originally added to
3728 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3732 sys_chdir (const char * path
)
3734 path
= map_w32_filename (path
, NULL
);
3735 if (w32_unicode_filenames
)
3737 wchar_t newdir_w
[MAX_PATH
];
3739 if (filename_to_utf16 (path
, newdir_w
) == 0)
3740 return _wchdir (newdir_w
);
3745 char newdir_a
[MAX_PATH
];
3747 if (filename_to_ansi (path
, newdir_a
) == 0)
3748 return _chdir (newdir_a
);
3754 sys_chmod (const char * path
, int mode
)
3756 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3757 if (w32_unicode_filenames
)
3759 wchar_t path_w
[MAX_PATH
];
3761 filename_to_utf16 (path
, path_w
);
3762 return _wchmod (path_w
, mode
);
3766 char path_a
[MAX_PATH
];
3768 filename_to_ansi (path
, path_a
);
3769 return _chmod (path_a
, mode
);
3774 sys_creat (const char * path
, int mode
)
3776 path
= map_w32_filename (path
, NULL
);
3777 if (w32_unicode_filenames
)
3779 wchar_t path_w
[MAX_PATH
];
3781 filename_to_utf16 (path
, path_w
);
3782 return _wcreat (path_w
, mode
);
3786 char path_a
[MAX_PATH
];
3788 filename_to_ansi (path
, path_a
);
3789 return _creat (path_a
, mode
);
3794 sys_fopen (const char * path
, const char * mode
)
3798 const char * mode_save
= mode
;
3800 /* Force all file handles to be non-inheritable. This is necessary to
3801 ensure child processes don't unwittingly inherit handles that might
3802 prevent future file access. */
3806 else if (mode
[0] == 'w' || mode
[0] == 'a')
3807 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3811 /* Only do simplistic option parsing. */
3815 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3818 else if (mode
[0] == 'b')
3823 else if (mode
[0] == 't')
3830 path
= map_w32_filename (path
, NULL
);
3831 if (w32_unicode_filenames
)
3833 wchar_t path_w
[MAX_PATH
];
3835 filename_to_utf16 (path
, path_w
);
3836 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3840 char path_a
[MAX_PATH
];
3842 filename_to_ansi (path
, path_a
);
3843 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3848 return _fdopen (fd
, mode_save
);
3851 /* This only works on NTFS volumes, but is useful to have. */
3853 sys_link (const char * old
, const char * new)
3857 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3858 wchar_t oldname_w
[MAX_PATH
];
3859 char oldname_a
[MAX_PATH
];
3861 if (old
== NULL
|| new == NULL
)
3867 strcpy (oldname
, map_w32_filename (old
, NULL
));
3868 strcpy (newname
, map_w32_filename (new, NULL
));
3870 if (w32_unicode_filenames
)
3872 filename_to_utf16 (oldname
, oldname_w
);
3873 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
3874 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3878 filename_to_ansi (oldname
, oldname_a
);
3879 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
3880 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3882 if (fileh
!= INVALID_HANDLE_VALUE
)
3886 /* Confusingly, the "alternate" stream name field does not apply
3887 when restoring a hard link, and instead contains the actual
3888 stream data for the link (ie. the name of the link to create).
3889 The WIN32_STREAM_ID structure before the cStreamName field is
3890 the stream header, which is then immediately followed by the
3894 WIN32_STREAM_ID wid
;
3895 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3898 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
3899 indicates that flag is unsupported for CP_UTF8, and OTOH says
3900 it is the default anyway. */
3901 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
3902 data
.wid
.cStreamName
, MAX_PATH
);
3905 LPVOID context
= NULL
;
3908 data
.wid
.dwStreamId
= BACKUP_LINK
;
3909 data
.wid
.dwStreamAttributes
= 0;
3910 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3911 data
.wid
.Size
.HighPart
= 0;
3912 data
.wid
.dwStreamNameSize
= 0;
3914 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3915 offsetof (WIN32_STREAM_ID
, cStreamName
)
3916 + data
.wid
.Size
.LowPart
,
3917 &wbytes
, FALSE
, FALSE
, &context
)
3918 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3925 DWORD err
= GetLastError ();
3930 case ERROR_ACCESS_DENIED
:
3931 /* This is what happens when OLDNAME is a directory,
3932 since Windows doesn't support hard links to
3933 directories. Posix says to set errno to EPERM in
3935 if (w32_unicode_filenames
)
3936 attributes
= GetFileAttributesW (oldname_w
);
3938 attributes
= GetFileAttributesA (oldname_a
);
3939 if (attributes
!= -1
3940 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
3942 else if (attributes
== -1
3943 && is_unc_volume (oldname
)
3944 && unc_volume_file_attributes (oldname
) != -1)
3949 case ERROR_TOO_MANY_LINKS
:
3952 case ERROR_NOT_SAME_DEVICE
:
3962 CloseHandle (fileh
);
3971 sys_mkdir (const char * path
)
3973 path
= map_w32_filename (path
, NULL
);
3975 if (w32_unicode_filenames
)
3977 wchar_t path_w
[MAX_PATH
];
3979 filename_to_utf16 (path
, path_w
);
3980 return _wmkdir (path_w
);
3984 char path_a
[MAX_PATH
];
3986 filename_to_ansi (path
, path_a
);
3987 return _mkdir (path_a
);
3992 sys_open (const char * path
, int oflag
, int mode
)
3994 const char* mpath
= map_w32_filename (path
, NULL
);
3997 if (w32_unicode_filenames
)
3999 wchar_t mpath_w
[MAX_PATH
];
4001 filename_to_utf16 (mpath
, mpath_w
);
4002 /* If possible, try to open file without _O_CREAT, to be able to
4003 write to existing hidden and system files. Force all file
4004 handles to be non-inheritable. */
4005 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4006 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4008 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4012 char mpath_a
[MAX_PATH
];
4014 filename_to_ansi (mpath
, mpath_a
);
4015 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4016 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4018 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4024 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4027 Standard algorithm for generating a temporary file name seems to be
4028 use pid or tid with a letter on the front (in place of the 6 X's)
4029 and cycle through the letters to find a unique name. We extend
4030 that to allow any reasonable character as the first of the 6 X's,
4031 so that the number of simultaneously used temporary files will be
4035 mkostemp (char * template, int flags
)
4039 unsigned uid
= GetCurrentThreadId ();
4040 int save_errno
= errno
;
4041 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4044 if (template == NULL
)
4047 p
= template + strlen (template);
4049 /* replace up to the last 5 X's with uid in decimal */
4050 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4052 p
[0] = '0' + uid
% 10;
4056 if (i
< 0 && p
[0] == 'X')
4061 p
[0] = first_char
[i
];
4062 if ((fd
= sys_open (template,
4063 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4064 S_IRUSR
| S_IWUSR
)) >= 0
4072 while (++i
< sizeof (first_char
));
4075 /* Template is badly formed or else we can't generate a unique name. */
4080 fchmod (int fd
, mode_t mode
)
4086 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4089 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4092 bool have_temp_a
= false;
4094 /* MoveFile on Windows 95 doesn't correctly change the short file name
4095 alias in a number of circumstances (it is not easy to predict when
4096 just by looking at oldname and newname, unfortunately). In these
4097 cases, renaming through a temporary name avoids the problem.
4099 A second problem on Windows 95 is that renaming through a temp name when
4100 newname is uppercase fails (the final long name ends up in
4101 lowercase, although the short alias might be uppercase) UNLESS the
4102 long temp name is not 8.3.
4104 So, on Windows 95 we always rename through a temp name, and we make sure
4105 the temp name has a long extension to ensure correct renaming. */
4107 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4109 /* volume_info is set indirectly by map_w32_filename. */
4110 oldname_dev
= volume_info
.serialnum
;
4112 if (os_subtype
== OS_9X
)
4117 char oldname_a
[MAX_PATH
];
4119 oldname
= map_w32_filename (oldname
, NULL
);
4120 filename_to_ansi (oldname
, oldname_a
);
4121 filename_to_ansi (temp
, temp_a
);
4122 if ((o
= strrchr (oldname_a
, '\\')))
4125 o
= (char *) oldname_a
;
4127 if ((p
= strrchr (temp_a
, '\\')))
4134 /* Force temp name to require a manufactured 8.3 alias - this
4135 seems to make the second rename work properly. */
4136 sprintf (p
, "_.%s.%u", o
, i
);
4138 result
= rename (oldname_a
, temp_a
);
4140 /* This loop must surely terminate! */
4141 while (result
< 0 && errno
== EEXIST
);
4147 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4148 (at least if it is a file; don't do this for directories).
4150 Since we mustn't do this if we are just changing the case of the
4151 file name (we would end up deleting the file we are trying to
4152 rename!), we let rename detect if the destination file already
4153 exists - that way we avoid the possible pitfalls of trying to
4154 determine ourselves whether two names really refer to the same
4155 file, which is not always possible in the general case. (Consider
4156 all the permutations of shared or subst'd drives, etc.) */
4158 newname
= map_w32_filename (newname
, NULL
);
4160 /* volume_info is set indirectly by map_w32_filename. */
4161 newname_dev
= volume_info
.serialnum
;
4163 if (w32_unicode_filenames
)
4165 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4167 filename_to_utf16 (temp
, temp_w
);
4168 filename_to_utf16 (newname
, newname_w
);
4169 result
= _wrename (temp_w
, newname_w
);
4170 if (result
< 0 && force
)
4172 DWORD w32err
= GetLastError ();
4175 && newname_dev
!= oldname_dev
)
4177 /* The implementation of `rename' on Windows does not return
4178 errno = EXDEV when you are moving a directory to a
4179 different storage device (ex. logical disk). It returns
4180 EACCES instead. So here we handle such situations and
4184 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4185 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4188 else if (errno
== EEXIST
)
4190 if (_wchmod (newname_w
, 0666) != 0)
4192 if (_wunlink (newname_w
) != 0)
4194 result
= _wrename (temp_w
, newname_w
);
4196 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4197 && is_symlink (temp
))
4199 /* This is Windows prohibiting the user from creating a
4200 symlink in another place, since that requires
4208 char newname_a
[MAX_PATH
];
4211 filename_to_ansi (temp
, temp_a
);
4212 filename_to_ansi (newname
, newname_a
);
4213 result
= rename (temp_a
, newname_a
);
4214 if (result
< 0 && force
)
4216 DWORD w32err
= GetLastError ();
4219 && newname_dev
!= oldname_dev
)
4223 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4224 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4227 else if (errno
== EEXIST
)
4229 if (_chmod (newname_a
, 0666) != 0)
4231 if (_unlink (newname_a
) != 0)
4233 result
= rename (temp_a
, newname_a
);
4235 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4236 && is_symlink (temp
))
4245 sys_rename (char const *old
, char const *new)
4247 return sys_rename_replace (old
, new, TRUE
);
4251 sys_rmdir (const char * path
)
4253 path
= map_w32_filename (path
, NULL
);
4255 if (w32_unicode_filenames
)
4257 wchar_t path_w
[MAX_PATH
];
4259 filename_to_utf16 (path
, path_w
);
4260 return _wrmdir (path_w
);
4264 char path_a
[MAX_PATH
];
4266 filename_to_ansi (path
, path_a
);
4267 return _rmdir (path_a
);
4272 sys_unlink (const char * path
)
4274 path
= map_w32_filename (path
, NULL
);
4276 if (w32_unicode_filenames
)
4278 wchar_t path_w
[MAX_PATH
];
4280 filename_to_utf16 (path
, path_w
);
4281 /* On Unix, unlink works without write permission. */
4282 _wchmod (path_w
, 0666);
4283 return _wunlink (path_w
);
4287 char path_a
[MAX_PATH
];
4289 filename_to_ansi (path
, path_a
);
4290 _chmod (path_a
, 0666);
4291 return _unlink (path_a
);
4295 static FILETIME utc_base_ft
;
4296 static ULONGLONG utc_base
; /* In 100ns units */
4297 static int init
= 0;
4299 #define FILETIME_TO_U64(result, ft) \
4301 ULARGE_INTEGER uiTemp; \
4302 uiTemp.LowPart = (ft).dwLowDateTime; \
4303 uiTemp.HighPart = (ft).dwHighDateTime; \
4304 result = uiTemp.QuadPart; \
4308 initialize_utc_base (void)
4310 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4319 st
.wMilliseconds
= 0;
4321 SystemTimeToFileTime (&st
, &utc_base_ft
);
4322 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4326 convert_time (FILETIME ft
)
4332 initialize_utc_base ();
4336 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4339 FILETIME_TO_U64 (tmp
, ft
);
4340 return (time_t) ((tmp
- utc_base
) / 10000000L);
4344 convert_from_time_t (time_t time
, FILETIME
* pft
)
4350 initialize_utc_base ();
4354 /* time in 100ns units since 1-Jan-1601 */
4355 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4356 pft
->dwHighDateTime
= tmp
.HighPart
;
4357 pft
->dwLowDateTime
= tmp
.LowPart
;
4360 static PSECURITY_DESCRIPTOR
4361 get_file_security_desc_by_handle (HANDLE h
)
4363 PSECURITY_DESCRIPTOR psd
= NULL
;
4365 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4366 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4368 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4369 NULL
, NULL
, NULL
, NULL
, &psd
);
4370 if (err
!= ERROR_SUCCESS
)
4376 static PSECURITY_DESCRIPTOR
4377 get_file_security_desc_by_name (const char *fname
)
4379 PSECURITY_DESCRIPTOR psd
= NULL
;
4381 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4382 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4384 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4386 err
= GetLastError ();
4387 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4391 psd
= xmalloc (sd_len
);
4392 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4404 unsigned n_subauthorities
;
4406 /* Use the last sub-authority value of the RID, the relative
4407 portion of the SID, as user/group ID. */
4408 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4409 if (n_subauthorities
< 1)
4410 return 0; /* the "World" RID */
4411 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4414 /* Caching SID and account values for faster lokup. */
4418 struct w32_id
*next
;
4420 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4423 static struct w32_id
*w32_idlist
;
4426 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4428 struct w32_id
*tail
, *found
;
4430 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4432 if (equal_sid ((PSID
)tail
->sid
, sid
))
4441 strcpy (name
, found
->name
);
4449 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4452 struct w32_id
*new_entry
;
4454 /* We don't want to leave behind stale cache from when Emacs was
4458 sid_len
= get_length_sid (sid
);
4459 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4462 new_entry
->rid
= id
;
4463 strcpy (new_entry
->name
, name
);
4464 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4465 new_entry
->next
= w32_idlist
;
4466 w32_idlist
= new_entry
;
4475 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4479 SID_NAME_USE ignore
;
4481 DWORD name_len
= sizeof (name
);
4483 DWORD domain_len
= sizeof (domain
);
4488 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4489 else if (what
== GID
)
4490 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4494 if (!result
|| !is_valid_sid (sid
))
4496 else if (!w32_cached_id (sid
, id
, nm
))
4498 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4499 domain
, &domain_len
, &ignore
)
4500 || name_len
> UNLEN
+1)
4504 *id
= get_rid (sid
);
4506 w32_add_to_cache (sid
, *id
, name
);
4513 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4515 int dflt_usr
= 0, dflt_grp
= 0;
4524 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4526 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4529 /* Consider files to belong to current user/group, if we cannot get
4530 more accurate information. */
4533 st
->st_uid
= dflt_passwd
.pw_uid
;
4534 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4538 st
->st_gid
= dflt_passwd
.pw_gid
;
4539 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4543 /* Return non-zero if NAME is a potentially slow filesystem. */
4545 is_slow_fs (const char *name
)
4550 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4551 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4552 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4553 devtype
= GetDriveType (NULL
); /* use root of current drive */
4556 /* GetDriveType needs the root directory of the drive. */
4557 strncpy (drive_root
, name
, 2);
4558 drive_root
[2] = '\\';
4559 drive_root
[3] = '\0';
4560 devtype
= GetDriveType (drive_root
);
4562 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4565 /* If this is non-zero, the caller wants accurate information about
4566 file's owner and group, which could be expensive to get. dired.c
4567 uses this flag when needed for the job at hand. */
4568 int w32_stat_get_owner_group
;
4570 /* MSVC stat function can't cope with UNC names and has other bugs, so
4571 replace it with our own. This also allows us to calculate consistent
4572 inode values and owner/group without hacks in the main Emacs code,
4573 and support file names encoded in UTF-8. */
4576 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4578 char *name
, *save_name
, *r
;
4579 WIN32_FIND_DATAW wfd_w
;
4580 WIN32_FIND_DATAA wfd_a
;
4582 unsigned __int64 fake_inode
= 0;
4585 int rootdir
= FALSE
;
4586 PSECURITY_DESCRIPTOR psd
= NULL
;
4587 int is_a_symlink
= 0;
4588 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4589 DWORD access_rights
= 0;
4590 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4591 FILETIME ctime
, atime
, wtime
;
4592 wchar_t name_w
[MAX_PATH
];
4593 char name_a
[MAX_PATH
];
4595 if (path
== NULL
|| buf
== NULL
)
4601 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4602 /* Must be valid filename, no wild cards or other invalid
4604 if (strpbrk (name
, "*?|<>\""))
4610 /* Remove trailing directory separator, unless name is the root
4611 directory of a drive or UNC volume in which case ensure there
4612 is a trailing separator. */
4613 len
= strlen (name
);
4614 name
= strcpy (alloca (len
+ 2), name
);
4616 /* Avoid a somewhat costly call to is_symlink if the filesystem
4617 doesn't support symlinks. */
4618 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4619 is_a_symlink
= is_symlink (name
);
4621 /* Plan A: Open the file and get all the necessary information via
4622 the resulting handle. This solves several issues in one blow:
4624 . retrieves attributes for the target of a symlink, if needed
4625 . gets attributes of root directories and symlinks pointing to
4626 root directories, thus avoiding the need for special-casing
4627 these and detecting them by examining the file-name format
4628 . retrieves more accurate attributes (e.g., non-zero size for
4629 some directories, esp. directories that are junction points)
4630 . correctly resolves "c:/..", "/.." and similar file names
4631 . avoids run-time penalties for 99% of use cases
4633 Plan A is always tried first, unless the user asked not to (but
4634 if the file is a symlink and we need to follow links, we try Plan
4635 A even if the user asked not to).
4637 If Plan A fails, we go to Plan B (below), where various
4638 potentially expensive techniques must be used to handle "special"
4639 files such as UNC volumes etc. */
4640 if (!(NILP (Vw32_get_true_file_attributes
)
4641 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4642 /* Following symlinks requires getting the info by handle. */
4643 || (is_a_symlink
&& follow_symlinks
))
4645 BY_HANDLE_FILE_INFORMATION info
;
4647 if (is_a_symlink
&& !follow_symlinks
)
4648 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4649 /* READ_CONTROL access rights are required to get security info
4650 by handle. But if the OS doesn't support security in the
4651 first place, we don't need to try. */
4652 if (is_windows_9x () != TRUE
)
4653 access_rights
|= READ_CONTROL
;
4655 if (w32_unicode_filenames
)
4657 filename_to_utf16 (name
, name_w
);
4658 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4660 /* If CreateFile fails with READ_CONTROL, try again with
4661 zero as access rights. */
4662 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4663 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4668 filename_to_ansi (name
, name_a
);
4669 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4671 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4672 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4675 if (fh
== INVALID_HANDLE_VALUE
)
4676 goto no_true_file_attributes
;
4678 /* This is more accurate in terms of getting the correct number
4679 of links, but is quite slow (it is noticeable when Emacs is
4680 making a list of file name completions). */
4681 if (GetFileInformationByHandle (fh
, &info
))
4683 nlinks
= info
.nNumberOfLinks
;
4684 /* Might as well use file index to fake inode values, but this
4685 is not guaranteed to be unique unless we keep a handle open
4686 all the time (even then there are situations where it is
4687 not unique). Reputedly, there are at most 48 bits of info
4688 (on NTFS, presumably less on FAT). */
4689 fake_inode
= info
.nFileIndexHigh
;
4691 fake_inode
+= info
.nFileIndexLow
;
4692 serialnum
= info
.dwVolumeSerialNumber
;
4693 fs_high
= info
.nFileSizeHigh
;
4694 fs_low
= info
.nFileSizeLow
;
4695 ctime
= info
.ftCreationTime
;
4696 atime
= info
.ftLastAccessTime
;
4697 wtime
= info
.ftLastWriteTime
;
4698 fattrs
= info
.dwFileAttributes
;
4702 /* We don't go to Plan B here, because it's not clear that
4703 it's a good idea. The only known use case where
4704 CreateFile succeeds, but GetFileInformationByHandle fails
4705 (with ERROR_INVALID_FUNCTION) is for character devices
4706 such as NUL, PRN, etc. For these, switching to Plan B is
4707 a net loss, because we lose the character device
4708 attribute returned by GetFileType below (FindFirstFile
4709 doesn't set that bit in the attributes), and the other
4710 fields don't make sense for character devices anyway.
4711 Emacs doesn't really care for non-file entities in the
4712 context of l?stat, so neither do we. */
4714 /* w32err is assigned so one could put a breakpoint here and
4715 examine its value, when GetFileInformationByHandle
4717 DWORD w32err
= GetLastError ();
4721 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4727 /* Test for a symlink before testing for a directory, since
4728 symlinks to directories have the directory bit set, but we
4729 don't want them to appear as directories. */
4730 if (is_a_symlink
&& !follow_symlinks
)
4731 buf
->st_mode
= S_IFLNK
;
4732 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4733 buf
->st_mode
= S_IFDIR
;
4736 DWORD ftype
= GetFileType (fh
);
4740 case FILE_TYPE_DISK
:
4741 buf
->st_mode
= S_IFREG
;
4743 case FILE_TYPE_PIPE
:
4744 buf
->st_mode
= S_IFIFO
;
4746 case FILE_TYPE_CHAR
:
4747 case FILE_TYPE_UNKNOWN
:
4749 buf
->st_mode
= S_IFCHR
;
4752 /* We produce the fallback owner and group data, based on the
4753 current user that runs Emacs, in the following cases:
4755 . caller didn't request owner and group info
4756 . this is Windows 9X
4757 . getting security by handle failed, and we need to produce
4758 information for the target of a symlink (this is better
4759 than producing a potentially misleading info about the
4762 If getting security by handle fails, and we don't need to
4763 resolve symlinks, we try getting security by name. */
4764 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4765 get_file_owner_and_group (NULL
, buf
);
4768 psd
= get_file_security_desc_by_handle (fh
);
4771 get_file_owner_and_group (psd
, buf
);
4774 else if (!(is_a_symlink
&& follow_symlinks
))
4776 psd
= get_file_security_desc_by_name (name
);
4777 get_file_owner_and_group (psd
, buf
);
4781 get_file_owner_and_group (NULL
, buf
);
4787 no_true_file_attributes
:
4788 /* Plan B: Either getting a handle on the file failed, or the
4789 caller explicitly asked us to not bother making this
4790 information more accurate.
4792 Implementation note: In Plan B, we never bother to resolve
4793 symlinks, even if we got here because we tried Plan A and
4794 failed. That's because, even if the caller asked for extra
4795 precision by setting Vw32_get_true_file_attributes to t,
4796 resolving symlinks requires acquiring a file handle to the
4797 symlink, which we already know will fail. And if the user
4798 did not ask for extra precision, resolving symlinks will fly
4799 in the face of that request, since the user then wants the
4800 lightweight version of the code. */
4801 rootdir
= (path
>= save_name
+ len
- 1
4802 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4804 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4805 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4806 if (IS_DIRECTORY_SEP (r
[0])
4807 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4810 /* Note: If NAME is a symlink to the root of a UNC volume
4811 (i.e. "\\SERVER"), we will not detect that here, and we will
4812 return data about the symlink as result of FindFirst below.
4813 This is unfortunate, but that marginal use case does not
4814 justify a call to chase_symlinks which would impose a penalty
4815 on all the other use cases. (We get here for symlinks to
4816 roots of UNC volumes because CreateFile above fails for them,
4817 unlike with symlinks to root directories X:\ of drives.) */
4818 if (is_unc_volume (name
))
4820 fattrs
= unc_volume_file_attributes (name
);
4824 ctime
= atime
= wtime
= utc_base_ft
;
4828 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4829 strcat (name
, "\\");
4830 if (GetDriveType (name
) < 2)
4836 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4837 ctime
= atime
= wtime
= utc_base_ft
;
4843 if (IS_DIRECTORY_SEP (name
[len
-1]))
4846 /* (This is hacky, but helps when doing file completions on
4847 network drives.) Optimize by using information available from
4848 active readdir if possible. */
4849 len
= strlen (dir_pathname
);
4850 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4852 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4853 && last_dir_find_data
!= -1
4854 && !(is_a_symlink
&& follow_symlinks
)
4855 /* The 2 file-name comparisons below support only ASCII
4856 characters, and will lose (compare not equal) when
4857 the file names include non-ASCII charcaters that are
4858 the same but for the case. However, doing this
4859 properly involves: (a) converting both file names to
4860 UTF-16, (b) lower-casing both names using CharLowerW,
4861 and (c) comparing the results; this would be quite a
4862 bit slower, whereas Plan B is for users who want
4863 lightweight albeit inaccurate version of 'stat'. */
4864 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
4865 && IS_DIRECTORY_SEP (name
[len
])
4866 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4868 have_wfd
= last_dir_find_data
;
4869 /* This was the last entry returned by readdir. */
4870 if (last_dir_find_data
== DIR_FIND_DATA_W
)
4871 wfd_w
= dir_find_data_w
;
4873 wfd_a
= dir_find_data_a
;
4877 logon_network_drive (name
);
4879 if (w32_unicode_filenames
)
4881 filename_to_utf16 (name
, name_w
);
4882 fh
= FindFirstFileW (name_w
, &wfd_w
);
4883 have_wfd
= DIR_FIND_DATA_W
;
4887 filename_to_ansi (name
, name_a
);
4888 /* If NAME includes characters not representable by
4889 the current ANSI codepage, filename_to_ansi
4890 usually replaces them with a '?'. We don't want
4891 to let FindFirstFileA interpret those as widlcards,
4892 and "succeed", returning us data from some random
4893 file in the same directory. */
4894 if (_mbspbrk (name_a
, "?"))
4895 fh
= INVALID_HANDLE_VALUE
;
4897 fh
= FindFirstFileA (name_a
, &wfd_a
);
4898 have_wfd
= DIR_FIND_DATA_A
;
4900 if (fh
== INVALID_HANDLE_VALUE
)
4907 /* Note: if NAME is a symlink, the information we get from
4908 FindFirstFile is for the symlink, not its target. */
4909 if (have_wfd
== DIR_FIND_DATA_W
)
4911 fattrs
= wfd_w
.dwFileAttributes
;
4912 ctime
= wfd_w
.ftCreationTime
;
4913 atime
= wfd_w
.ftLastAccessTime
;
4914 wtime
= wfd_w
.ftLastWriteTime
;
4915 fs_high
= wfd_w
.nFileSizeHigh
;
4916 fs_low
= wfd_w
.nFileSizeLow
;
4920 fattrs
= wfd_a
.dwFileAttributes
;
4921 ctime
= wfd_a
.ftCreationTime
;
4922 atime
= wfd_a
.ftLastAccessTime
;
4923 wtime
= wfd_a
.ftLastWriteTime
;
4924 fs_high
= wfd_a
.nFileSizeHigh
;
4925 fs_low
= wfd_a
.nFileSizeLow
;
4929 serialnum
= volume_info
.serialnum
;
4931 if (is_a_symlink
&& !follow_symlinks
)
4932 buf
->st_mode
= S_IFLNK
;
4933 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4934 buf
->st_mode
= S_IFDIR
;
4936 buf
->st_mode
= S_IFREG
;
4938 get_file_owner_and_group (NULL
, buf
);
4941 buf
->st_ino
= fake_inode
;
4943 buf
->st_dev
= serialnum
;
4944 buf
->st_rdev
= serialnum
;
4946 buf
->st_size
= fs_high
;
4947 buf
->st_size
<<= 32;
4948 buf
->st_size
+= fs_low
;
4949 buf
->st_nlink
= nlinks
;
4951 /* Convert timestamps to Unix format. */
4952 buf
->st_mtime
= convert_time (wtime
);
4953 buf
->st_atime
= convert_time (atime
);
4954 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4955 buf
->st_ctime
= convert_time (ctime
);
4956 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4958 /* determine rwx permissions */
4959 if (is_a_symlink
&& !follow_symlinks
)
4960 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
4963 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
4964 permission
= S_IREAD
;
4966 permission
= S_IREAD
| S_IWRITE
;
4968 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4969 permission
|= S_IEXEC
;
4970 else if (is_exec (name
))
4971 permission
|= S_IEXEC
;
4974 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
4980 stat (const char * path
, struct stat
* buf
)
4982 return stat_worker (path
, buf
, 1);
4986 lstat (const char * path
, struct stat
* buf
)
4988 return stat_worker (path
, buf
, 0);
4992 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
4994 /* Rely on a hack: an open directory is modeled as file descriptor 0.
4995 This is good enough for the current usage in Emacs, but is fragile.
4997 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
4998 Gnulib does this and can serve as a model. */
4999 char fullname
[MAX_UTF8_PATH
];
5003 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5006 errno
= ENAMETOOLONG
;
5012 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5015 /* Provide fstat and utime as well as stat for consistent handling of
5018 fstat (int desc
, struct stat
* buf
)
5020 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5021 BY_HANDLE_FILE_INFORMATION info
;
5022 unsigned __int64 fake_inode
;
5025 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5027 case FILE_TYPE_DISK
:
5028 buf
->st_mode
= S_IFREG
;
5029 if (!GetFileInformationByHandle (fh
, &info
))
5035 case FILE_TYPE_PIPE
:
5036 buf
->st_mode
= S_IFIFO
;
5038 case FILE_TYPE_CHAR
:
5039 case FILE_TYPE_UNKNOWN
:
5041 buf
->st_mode
= S_IFCHR
;
5043 memset (&info
, 0, sizeof (info
));
5044 info
.dwFileAttributes
= 0;
5045 info
.ftCreationTime
= utc_base_ft
;
5046 info
.ftLastAccessTime
= utc_base_ft
;
5047 info
.ftLastWriteTime
= utc_base_ft
;
5050 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5051 buf
->st_mode
= S_IFDIR
;
5053 buf
->st_nlink
= info
.nNumberOfLinks
;
5054 /* Might as well use file index to fake inode values, but this
5055 is not guaranteed to be unique unless we keep a handle open
5056 all the time (even then there are situations where it is
5057 not unique). Reputedly, there are at most 48 bits of info
5058 (on NTFS, presumably less on FAT). */
5059 fake_inode
= info
.nFileIndexHigh
;
5061 fake_inode
+= info
.nFileIndexLow
;
5063 /* MSVC defines _ino_t to be short; other libc's might not. */
5064 if (sizeof (buf
->st_ino
) == 2)
5065 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5067 buf
->st_ino
= fake_inode
;
5069 /* If the caller so requested, get the true file owner and group.
5070 Otherwise, consider the file to belong to the current user. */
5071 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5072 get_file_owner_and_group (NULL
, buf
);
5075 PSECURITY_DESCRIPTOR psd
= NULL
;
5077 psd
= get_file_security_desc_by_handle (fh
);
5080 get_file_owner_and_group (psd
, buf
);
5084 get_file_owner_and_group (NULL
, buf
);
5087 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5088 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5090 buf
->st_size
= info
.nFileSizeHigh
;
5091 buf
->st_size
<<= 32;
5092 buf
->st_size
+= info
.nFileSizeLow
;
5094 /* Convert timestamps to Unix format. */
5095 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5096 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5097 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5098 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5099 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5101 /* determine rwx permissions */
5102 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5103 permission
= S_IREAD
;
5105 permission
= S_IREAD
| S_IWRITE
;
5107 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5108 permission
|= S_IEXEC
;
5111 #if 0 /* no way of knowing the filename */
5112 char * p
= strrchr (name
, '.');
5114 (xstrcasecmp (p
, ".exe") == 0 ||
5115 xstrcasecmp (p
, ".com") == 0 ||
5116 xstrcasecmp (p
, ".bat") == 0 ||
5117 xstrcasecmp (p
, ".cmd") == 0))
5118 permission
|= S_IEXEC
;
5122 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5127 /* A version of 'utime' which handles directories as well as
5131 utime (const char *name
, struct utimbuf
*times
)
5133 struct utimbuf deftime
;
5140 deftime
.modtime
= deftime
.actime
= time (NULL
);
5144 if (w32_unicode_filenames
)
5146 wchar_t name_utf16
[MAX_PATH
];
5148 if (filename_to_utf16 (name
, name_utf16
) != 0)
5149 return -1; /* errno set by filename_to_utf16 */
5151 /* Need write access to set times. */
5152 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5153 /* If NAME specifies a directory, FILE_SHARE_DELETE
5154 allows other processes to delete files inside it,
5155 while we have the directory open. */
5156 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5157 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5161 char name_ansi
[MAX_PATH
];
5163 if (filename_to_ansi (name
, name_ansi
) != 0)
5164 return -1; /* errno set by filename_to_ansi */
5166 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5167 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5168 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5170 if (fh
!= INVALID_HANDLE_VALUE
)
5172 convert_from_time_t (times
->actime
, &atime
);
5173 convert_from_time_t (times
->modtime
, &mtime
);
5174 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5184 DWORD err
= GetLastError ();
5188 case ERROR_FILE_NOT_FOUND
:
5189 case ERROR_PATH_NOT_FOUND
:
5190 case ERROR_INVALID_DRIVE
:
5191 case ERROR_BAD_NETPATH
:
5192 case ERROR_DEV_NOT_EXIST
:
5193 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5194 file name includes ?s, i.e. translation to ANSI failed. */
5195 case ERROR_INVALID_NAME
:
5198 case ERROR_TOO_MANY_OPEN_FILES
:
5201 case ERROR_ACCESS_DENIED
:
5202 case ERROR_SHARING_VIOLATION
:
5215 /* Symlink-related functions. */
5216 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5217 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5221 symlink (char const *filename
, char const *linkname
)
5223 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5225 int dir_access
, filename_ends_in_slash
;
5227 /* Diagnostics follows Posix as much as possible. */
5228 if (filename
== NULL
|| linkname
== NULL
)
5238 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5240 errno
= ENAMETOOLONG
;
5244 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5245 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5251 /* Note: since empty FILENAME was already rejected, we can safely
5252 refer to FILENAME[1]. */
5253 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5255 /* Non-absolute FILENAME is understood as being relative to
5256 LINKNAME's directory. We need to prepend that directory to
5257 FILENAME to get correct results from faccessat below, since
5258 otherwise it will interpret FILENAME relative to the
5259 directory where the Emacs process runs. Note that
5260 make-symbolic-link always makes sure LINKNAME is a fully
5261 expanded file name. */
5262 char tem
[MAX_UTF8_PATH
];
5263 char *p
= linkfn
+ strlen (linkfn
);
5265 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5268 strncpy (tem
, linkfn
, p
- linkfn
);
5269 tem
[p
- linkfn
] = '\0';
5270 strcat (tem
, filename
);
5271 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5274 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5276 /* Since Windows distinguishes between symlinks to directories and
5277 to files, we provide a kludgy feature: if FILENAME doesn't
5278 exist, but ends in a slash, we create a symlink to directory. If
5279 FILENAME exists and is a directory, we always create a symlink to
5281 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5282 if (dir_access
== 0 || filename_ends_in_slash
)
5283 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5285 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5286 if (filename_ends_in_slash
)
5287 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5290 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5292 /* ENOSYS is set by create_symbolic_link, when it detects that
5293 the OS doesn't support the CreateSymbolicLink API. */
5294 if (errno
!= ENOSYS
)
5296 DWORD w32err
= GetLastError ();
5300 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5301 TGTFN point to the same file name, go figure. */
5303 case ERROR_FILE_EXISTS
:
5306 case ERROR_ACCESS_DENIED
:
5309 case ERROR_FILE_NOT_FOUND
:
5310 case ERROR_PATH_NOT_FOUND
:
5311 case ERROR_BAD_NETPATH
:
5312 case ERROR_INVALID_REPARSE_DATA
:
5315 case ERROR_DIRECTORY
:
5318 case ERROR_PRIVILEGE_NOT_HELD
:
5319 case ERROR_NOT_ALL_ASSIGNED
:
5322 case ERROR_DISK_FULL
:
5335 /* A quick inexpensive test of whether FILENAME identifies a file that
5336 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5337 must already be in the normalized form returned by
5340 Note: for repeated operations on many files, it is best to test
5341 whether the underlying volume actually supports symlinks, by
5342 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5343 avoid the call to this function if it doesn't. That's because the
5344 call to GetFileAttributes takes a non-negligible time, especially
5345 on non-local or removable filesystems. See stat_worker for an
5346 example of how to do that. */
5348 is_symlink (const char *filename
)
5351 wchar_t filename_w
[MAX_PATH
];
5352 char filename_a
[MAX_PATH
];
5353 WIN32_FIND_DATAW wfdw
;
5354 WIN32_FIND_DATAA wfda
;
5356 int attrs_mean_symlink
;
5358 if (w32_unicode_filenames
)
5360 filename_to_utf16 (filename
, filename_w
);
5361 attrs
= GetFileAttributesW (filename_w
);
5365 filename_to_ansi (filename
, filename_a
);
5366 attrs
= GetFileAttributesA (filename_a
);
5370 DWORD w32err
= GetLastError ();
5374 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5376 case ERROR_ACCESS_DENIED
:
5379 case ERROR_FILE_NOT_FOUND
:
5380 case ERROR_PATH_NOT_FOUND
:
5387 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5389 logon_network_drive (filename
);
5390 if (w32_unicode_filenames
)
5392 fh
= FindFirstFileW (filename_w
, &wfdw
);
5393 attrs_mean_symlink
=
5394 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5395 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5397 else if (_mbspbrk (filename_a
, "?"))
5399 /* filename_to_ansi failed to convert the file name. */
5405 fh
= FindFirstFileA (filename_a
, &wfda
);
5406 attrs_mean_symlink
=
5407 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5408 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5410 if (fh
== INVALID_HANDLE_VALUE
)
5413 return attrs_mean_symlink
;
5416 /* If NAME identifies a symbolic link, copy into BUF the file name of
5417 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5418 null-terminate the target name, even if it fits. Return the number
5419 of bytes copied, or -1 if NAME is not a symlink or any error was
5420 encountered while resolving it. The file name copied into BUF is
5421 encoded in the current ANSI codepage. */
5423 readlink (const char *name
, char *buf
, size_t buf_size
)
5426 TOKEN_PRIVILEGES privs
;
5427 int restore_privs
= 0;
5430 char resolved
[MAX_UTF8_PATH
];
5443 path
= map_w32_filename (name
, NULL
);
5445 if (strlen (path
) > MAX_UTF8_PATH
)
5447 errno
= ENAMETOOLONG
;
5452 if (is_windows_9x () == TRUE
5453 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5454 || !is_symlink (path
))
5457 errno
= EINVAL
; /* not a symlink */
5461 /* Done with simple tests, now we're in for some _real_ work. */
5462 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5464 /* Implementation note: From here and onward, don't return early,
5465 since that will fail to restore the original set of privileges of
5466 the calling thread. */
5468 retval
= -1; /* not too optimistic, are we? */
5470 /* Note: In the next call to CreateFile, we use zero as the 2nd
5471 argument because, when the symlink is a hidden/system file,
5472 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5473 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5474 and directory symlinks. */
5475 if (w32_unicode_filenames
)
5477 wchar_t path_w
[MAX_PATH
];
5479 filename_to_utf16 (path
, path_w
);
5480 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5481 FILE_FLAG_OPEN_REPARSE_POINT
5482 | FILE_FLAG_BACKUP_SEMANTICS
,
5487 char path_a
[MAX_PATH
];
5489 filename_to_ansi (path
, path_a
);
5490 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5491 FILE_FLAG_OPEN_REPARSE_POINT
5492 | FILE_FLAG_BACKUP_SEMANTICS
,
5495 if (sh
!= INVALID_HANDLE_VALUE
)
5497 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5498 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5501 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5502 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5505 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5509 /* Copy the link target name, in wide characters, from
5510 reparse_data, then convert it to multibyte encoding in
5511 the current locale's codepage. */
5515 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5517 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5518 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5519 size_t size_to_copy
= buf_size
;
5521 /* According to MSDN, PrintNameLength does not include the
5522 terminating null character. */
5523 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5524 memcpy (lwname
, lwname_src
, lwname_len
);
5525 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5526 filename_from_utf16 (lwname
, resolved
);
5527 dostounix_filename (resolved
);
5528 lname_size
= strlen (resolved
) + 1;
5529 if (lname_size
<= buf_size
)
5530 size_to_copy
= lname_size
;
5531 strncpy (buf
, resolved
, size_to_copy
);
5533 retval
= size_to_copy
;
5539 /* CreateFile failed. */
5540 DWORD w32err2
= GetLastError ();
5544 case ERROR_FILE_NOT_FOUND
:
5545 case ERROR_PATH_NOT_FOUND
:
5548 case ERROR_ACCESS_DENIED
:
5549 case ERROR_TOO_MANY_OPEN_FILES
:
5559 restore_privilege (&privs
);
5567 readlinkat (int fd
, char const *name
, char *buffer
,
5570 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5571 as in fstatat. FIXME: Add proper support for readlinkat. */
5572 char fullname
[MAX_UTF8_PATH
];
5576 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5579 errno
= ENAMETOOLONG
;
5585 return readlink (name
, buffer
, buffer_size
);
5588 /* If FILE is a symlink, return its target (stored in a static
5589 buffer); otherwise return FILE.
5591 This function repeatedly resolves symlinks in the last component of
5592 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5593 until it arrives at a file whose last component is not a symlink,
5594 or some error occurs. It returns the target of the last
5595 successfully resolved symlink in the chain. If it succeeds to
5596 resolve even a single symlink, the value returned is an absolute
5597 file name with backslashes (result of GetFullPathName). By
5598 contrast, if the original FILE is returned, it is unaltered.
5600 Note: This function can set errno even if it succeeds.
5602 Implementation note: we only resolve the last portion ("basename")
5603 of the argument FILE and of each following file in the chain,
5604 disregarding any possible symlinks in its leading directories.
5605 This is because Windows system calls and library functions
5606 transparently resolve symlinks in leading directories and return
5607 correct information, as long as the basename is not a symlink. */
5609 chase_symlinks (const char *file
)
5611 static char target
[MAX_UTF8_PATH
];
5612 char link
[MAX_UTF8_PATH
];
5613 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5614 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5615 ssize_t res
, link_len
;
5618 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5619 return (char *)file
;
5621 if (w32_unicode_filenames
)
5623 wchar_t file_w
[MAX_PATH
];
5625 filename_to_utf16 (file
, file_w
);
5626 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5627 return (char *)file
;
5628 filename_from_utf16 (link_w
, link
);
5632 char file_a
[MAX_PATH
];
5634 filename_to_ansi (file
, file_a
);
5635 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5636 return (char *)file
;
5637 filename_from_ansi (link_a
, link
);
5639 link_len
= strlen (link
);
5644 /* Remove trailing slashes, as we want to resolve the last
5645 non-trivial part of the link name. */
5646 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5647 link
[link_len
--] = '\0';
5649 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5653 if (!(IS_DEVICE_SEP (target
[1])
5654 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5656 /* Target is relative. Append it to the directory part of
5657 the symlink, then copy the result back to target. */
5658 char *p
= link
+ link_len
;
5660 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5663 strcpy (target
, link
);
5665 /* Resolve any "." and ".." to get a fully-qualified file name
5667 if (w32_unicode_filenames
)
5669 filename_to_utf16 (target
, target_w
);
5670 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5672 filename_from_utf16 (link_w
, link
);
5676 filename_to_ansi (target
, target_a
);
5677 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5679 filename_from_ansi (link_a
, link
);
5681 link_len
= strlen (link
);
5683 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5685 if (loop_count
> 100)
5688 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5689 return (char *)file
;
5694 /* Posix ACL emulation. */
5697 acl_valid (acl_t acl
)
5699 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5703 acl_to_text (acl_t acl
, ssize_t
*size
)
5706 SECURITY_INFORMATION flags
=
5707 OWNER_SECURITY_INFORMATION
|
5708 GROUP_SECURITY_INFORMATION
|
5709 DACL_SECURITY_INFORMATION
;
5710 char *retval
= NULL
;
5716 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5719 /* We don't want to mix heaps, so we duplicate the string in our
5720 heap and free the one allocated by the API. */
5721 retval
= xstrdup (str_acl
);
5724 LocalFree (str_acl
);
5726 else if (errno
!= ENOTSUP
)
5733 acl_from_text (const char *acl_str
)
5735 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5741 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5744 retval
= xmalloc (sd_size
);
5745 memcpy (retval
, psd
, sd_size
);
5748 else if (errno
!= ENOTSUP
)
5755 acl_free (void *ptr
)
5762 acl_get_file (const char *fname
, acl_type_t type
)
5764 PSECURITY_DESCRIPTOR psd
= NULL
;
5765 const char *filename
;
5767 if (type
== ACL_TYPE_ACCESS
)
5770 SECURITY_INFORMATION si
=
5771 OWNER_SECURITY_INFORMATION
|
5772 GROUP_SECURITY_INFORMATION
|
5773 DACL_SECURITY_INFORMATION
;
5776 filename
= map_w32_filename (fname
, NULL
);
5777 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5778 fname
= chase_symlinks (filename
);
5783 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5784 && errno
!= ENOTSUP
)
5786 err
= GetLastError ();
5787 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5789 psd
= xmalloc (sd_len
);
5790 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5797 else if (err
== ERROR_FILE_NOT_FOUND
5798 || err
== ERROR_PATH_NOT_FOUND
5799 /* ERROR_INVALID_NAME is what we get if
5800 w32-unicode-filenames is nil and the file cannot
5801 be encoded in the current ANSI codepage. */
5802 || err
== ERROR_INVALID_NAME
)
5810 else if (type
!= ACL_TYPE_DEFAULT
)
5817 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5819 TOKEN_PRIVILEGES old1
, old2
;
5821 int st
= 0, retval
= -1;
5822 SECURITY_INFORMATION flags
= 0;
5828 const char *filename
;
5830 if (acl_valid (acl
) != 0
5831 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5837 if (type
== ACL_TYPE_DEFAULT
)
5843 filename
= map_w32_filename (fname
, NULL
);
5844 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5845 fname
= chase_symlinks (filename
);
5849 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5851 flags
|= OWNER_SECURITY_INFORMATION
;
5852 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5854 flags
|= GROUP_SECURITY_INFORMATION
;
5855 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5858 flags
|= DACL_SECURITY_INFORMATION
;
5862 /* According to KB-245153, setting the owner will succeed if either:
5863 (1) the caller is the user who will be the new owner, and has the
5864 SE_TAKE_OWNERSHIP privilege, or
5865 (2) the caller has the SE_RESTORE privilege, in which case she can
5866 set any valid user or group as the owner
5868 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5869 privileges, and disregard any failures in obtaining them. If
5870 these privileges cannot be obtained, and do not already exist in
5871 the calling thread's security token, this function could fail
5873 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5875 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5880 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5882 err
= GetLastError ();
5884 if (errno
== ENOTSUP
)
5886 else if (err
== ERROR_INVALID_OWNER
5887 || err
== ERROR_NOT_ALL_ASSIGNED
5888 || err
== ERROR_ACCESS_DENIED
)
5890 /* Maybe the requested ACL and the one the file already has
5891 are identical, in which case we can silently ignore the
5892 failure. (And no, Windows doesn't.) */
5893 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5898 char *acl_from
= acl_to_text (current_acl
, NULL
);
5899 char *acl_to
= acl_to_text (acl
, NULL
);
5901 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5907 acl_free (acl_from
);
5910 acl_free (current_acl
);
5913 else if (err
== ERROR_FILE_NOT_FOUND
5914 || err
== ERROR_PATH_NOT_FOUND
5915 /* ERROR_INVALID_NAME is what we get if
5916 w32-unicode-filenames is nil and the file cannot be
5917 encoded in the current ANSI codepage. */
5918 || err
== ERROR_INVALID_NAME
)
5932 restore_privilege (&old2
);
5933 restore_privilege (&old1
);
5941 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5942 have a fixed max size for file names, so we don't need the kind of
5943 alloc/malloc/realloc dance the gnulib version does. We also don't
5944 support FD-relative symlinks. */
5946 careadlinkat (int fd
, char const *filename
,
5947 char *buffer
, size_t buffer_size
,
5948 struct allocator
const *alloc
,
5949 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
5951 char linkname
[MAX_UTF8_PATH
];
5954 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
5958 char *retval
= buffer
;
5960 linkname
[link_size
++] = '\0';
5961 if (link_size
> buffer_size
)
5962 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
5964 memcpy (retval
, linkname
, link_size
);
5972 /* Support for browsing other processes and their attributes. See
5973 process.c for the Lisp bindings. */
5975 /* Helper wrapper functions. */
5977 static HANDLE WINAPI
5978 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
5980 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
5982 if (g_b_init_create_toolhelp32_snapshot
== 0)
5984 g_b_init_create_toolhelp32_snapshot
= 1;
5985 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
5986 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5987 "CreateToolhelp32Snapshot");
5989 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
5991 return INVALID_HANDLE_VALUE
;
5993 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
5997 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
5999 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6001 if (g_b_init_process32_first
== 0)
6003 g_b_init_process32_first
= 1;
6004 s_pfn_Process32_First
= (Process32First_Proc
)
6005 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6008 if (s_pfn_Process32_First
== NULL
)
6012 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6016 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6018 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6020 if (g_b_init_process32_next
== 0)
6022 g_b_init_process32_next
= 1;
6023 s_pfn_Process32_Next
= (Process32Next_Proc
)
6024 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6027 if (s_pfn_Process32_Next
== NULL
)
6031 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6035 open_thread_token (HANDLE ThreadHandle
,
6036 DWORD DesiredAccess
,
6038 PHANDLE TokenHandle
)
6040 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6041 HMODULE hm_advapi32
= NULL
;
6042 if (is_windows_9x () == TRUE
)
6044 SetLastError (ERROR_NOT_SUPPORTED
);
6047 if (g_b_init_open_thread_token
== 0)
6049 g_b_init_open_thread_token
= 1;
6050 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6051 s_pfn_Open_Thread_Token
=
6052 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6054 if (s_pfn_Open_Thread_Token
== NULL
)
6056 SetLastError (ERROR_NOT_SUPPORTED
);
6060 s_pfn_Open_Thread_Token (
6069 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6071 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6072 HMODULE hm_advapi32
= NULL
;
6073 if (is_windows_9x () == TRUE
)
6077 if (g_b_init_impersonate_self
== 0)
6079 g_b_init_impersonate_self
= 1;
6080 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6081 s_pfn_Impersonate_Self
=
6082 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6084 if (s_pfn_Impersonate_Self
== NULL
)
6088 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6092 revert_to_self (void)
6094 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6095 HMODULE hm_advapi32
= NULL
;
6096 if (is_windows_9x () == TRUE
)
6100 if (g_b_init_revert_to_self
== 0)
6102 g_b_init_revert_to_self
= 1;
6103 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6104 s_pfn_Revert_To_Self
=
6105 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6107 if (s_pfn_Revert_To_Self
== NULL
)
6111 return s_pfn_Revert_To_Self ();
6115 get_process_memory_info (HANDLE h_proc
,
6116 PPROCESS_MEMORY_COUNTERS mem_counters
,
6119 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6120 HMODULE hm_psapi
= NULL
;
6121 if (is_windows_9x () == TRUE
)
6125 if (g_b_init_get_process_memory_info
== 0)
6127 g_b_init_get_process_memory_info
= 1;
6128 hm_psapi
= LoadLibrary ("Psapi.dll");
6130 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6131 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6133 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6137 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6141 get_process_working_set_size (HANDLE h_proc
,
6145 static GetProcessWorkingSetSize_Proc
6146 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6148 if (is_windows_9x () == TRUE
)
6152 if (g_b_init_get_process_working_set_size
== 0)
6154 g_b_init_get_process_working_set_size
= 1;
6155 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6156 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6157 "GetProcessWorkingSetSize");
6159 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6163 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6167 global_memory_status (MEMORYSTATUS
*buf
)
6169 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6171 if (is_windows_9x () == TRUE
)
6175 if (g_b_init_global_memory_status
== 0)
6177 g_b_init_global_memory_status
= 1;
6178 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6179 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6180 "GlobalMemoryStatus");
6182 if (s_pfn_Global_Memory_Status
== NULL
)
6186 return s_pfn_Global_Memory_Status (buf
);
6190 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6192 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6194 if (is_windows_9x () == TRUE
)
6198 if (g_b_init_global_memory_status_ex
== 0)
6200 g_b_init_global_memory_status_ex
= 1;
6201 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6202 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6203 "GlobalMemoryStatusEx");
6205 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6209 return s_pfn_Global_Memory_Status_Ex (buf
);
6213 list_system_processes (void)
6215 struct gcpro gcpro1
;
6216 Lisp_Object proclist
= Qnil
;
6219 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6221 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6223 PROCESSENTRY32 proc_entry
;
6229 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6230 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6231 res
= process32_next (h_snapshot
, &proc_entry
))
6233 proc_id
= proc_entry
.th32ProcessID
;
6234 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6237 CloseHandle (h_snapshot
);
6239 proclist
= Fnreverse (proclist
);
6246 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6248 TOKEN_PRIVILEGES priv
;
6249 DWORD priv_size
= sizeof (priv
);
6250 DWORD opriv_size
= sizeof (*old_priv
);
6251 HANDLE h_token
= NULL
;
6252 HANDLE h_thread
= GetCurrentThread ();
6256 res
= open_thread_token (h_thread
,
6257 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6259 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6261 if (impersonate_self (SecurityImpersonation
))
6262 res
= open_thread_token (h_thread
,
6263 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6268 priv
.PrivilegeCount
= 1;
6269 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6270 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6271 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6272 old_priv
, &opriv_size
)
6273 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6277 CloseHandle (h_token
);
6283 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6285 DWORD priv_size
= sizeof (*priv
);
6286 HANDLE h_token
= NULL
;
6289 if (open_thread_token (GetCurrentThread (),
6290 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6293 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6294 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6298 CloseHandle (h_token
);
6304 ltime (ULONGLONG time_100ns
)
6306 ULONGLONG time_sec
= time_100ns
/ 10000000;
6307 int subsec
= time_100ns
% 10000000;
6308 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6309 subsec
/ 10, subsec
% 10 * 100000);
6312 #define U64_TO_LISP_TIME(time) ltime (time)
6315 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6316 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6319 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6320 ULONGLONG tem1
, tem2
, tem3
, tem
;
6323 || !get_process_times_fn
6324 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6325 &ft_kernel
, &ft_user
))
6328 GetSystemTimeAsFileTime (&ft_current
);
6330 FILETIME_TO_U64 (tem1
, ft_kernel
);
6331 *stime
= U64_TO_LISP_TIME (tem1
);
6333 FILETIME_TO_U64 (tem2
, ft_user
);
6334 *utime
= U64_TO_LISP_TIME (tem2
);
6337 *ttime
= U64_TO_LISP_TIME (tem3
);
6339 FILETIME_TO_U64 (tem
, ft_creation
);
6340 /* Process no 4 (System) returns zero creation time. */
6343 *ctime
= U64_TO_LISP_TIME (tem
);
6347 FILETIME_TO_U64 (tem3
, ft_current
);
6348 tem
= (tem3
- utc_base
) - tem
;
6350 *etime
= U64_TO_LISP_TIME (tem
);
6354 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6365 system_process_attributes (Lisp_Object pid
)
6367 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6368 Lisp_Object attrs
= Qnil
;
6369 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6370 HANDLE h_snapshot
, h_proc
;
6373 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6374 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6375 DWORD glength
= sizeof (gname
);
6376 HANDLE token
= NULL
;
6377 SID_NAME_USE user_type
;
6378 unsigned char *buf
= NULL
;
6380 TOKEN_USER user_token
;
6381 TOKEN_PRIMARY_GROUP group_token
;
6384 PROCESS_MEMORY_COUNTERS mem
;
6385 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6386 SIZE_T minrss
, maxrss
;
6388 MEMORY_STATUS_EX memstex
;
6389 double totphys
= 0.0;
6390 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6392 BOOL result
= FALSE
;
6394 CHECK_NUMBER_OR_FLOAT (pid
);
6395 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6397 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6399 GCPRO3 (attrs
, decoded_cmd
, tem
);
6401 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6406 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6407 for (res
= process32_first (h_snapshot
, &pe
); res
;
6408 res
= process32_next (h_snapshot
, &pe
))
6410 if (proc_id
== pe
.th32ProcessID
)
6413 decoded_cmd
= build_string ("Idle");
6416 /* Decode the command name from locale-specific
6418 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6421 code_convert_string_norecord (cmd_str
,
6422 Vlocale_coding_system
, 0);
6424 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6425 attrs
= Fcons (Fcons (Qppid
,
6426 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6428 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6430 attrs
= Fcons (Fcons (Qthcount
,
6431 make_fixnum_or_float (pe
.cntThreads
)),
6438 CloseHandle (h_snapshot
);
6447 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6449 /* If we were denied a handle to the process, try again after
6450 enabling the SeDebugPrivilege in our process. */
6453 TOKEN_PRIVILEGES priv_current
;
6455 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6457 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6459 restore_privilege (&priv_current
);
6465 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6468 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6469 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6471 buf
= xmalloc (blen
);
6472 result
= get_token_information (token
, TokenUser
,
6473 (LPVOID
)buf
, blen
, &needed
);
6476 memcpy (&user_token
, buf
, sizeof (user_token
));
6477 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6479 euid
= get_rid (user_token
.User
.Sid
);
6480 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6485 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6488 strcpy (uname
, "unknown");
6492 ulength
= strlen (uname
);
6498 /* Determine a reasonable euid and gid values. */
6499 if (xstrcasecmp ("administrator", uname
) == 0)
6501 euid
= 500; /* well-known Administrator uid */
6502 egid
= 513; /* well-known None gid */
6506 /* Get group id and name. */
6507 result
= get_token_information (token
, TokenPrimaryGroup
,
6508 (LPVOID
)buf
, blen
, &needed
);
6509 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6511 buf
= xrealloc (buf
, blen
= needed
);
6512 result
= get_token_information (token
, TokenPrimaryGroup
,
6513 (LPVOID
)buf
, blen
, &needed
);
6517 memcpy (&group_token
, buf
, sizeof (group_token
));
6518 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6520 egid
= get_rid (group_token
.PrimaryGroup
);
6521 dlength
= sizeof (domain
);
6523 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6524 gname
, &glength
, NULL
, &dlength
,
6527 w32_add_to_cache (group_token
.PrimaryGroup
,
6531 strcpy (gname
, "None");
6535 glength
= strlen (gname
);
6543 if (!is_windows_9x ())
6545 /* We couldn't open the process token, presumably because of
6546 insufficient access rights. Assume this process is run
6548 strcpy (uname
, "SYSTEM");
6549 strcpy (gname
, "None");
6550 euid
= 18; /* SYSTEM */
6551 egid
= 513; /* None */
6552 glength
= strlen (gname
);
6553 ulength
= strlen (uname
);
6555 /* If we are running under Windows 9X, where security calls are
6556 not supported, we assume all processes are run by the current
6558 else if (GetUserName (uname
, &ulength
))
6560 if (xstrcasecmp ("administrator", uname
) == 0)
6565 strcpy (gname
, "None");
6566 glength
= strlen (gname
);
6567 ulength
= strlen (uname
);
6573 strcpy (uname
, "administrator");
6574 ulength
= strlen (uname
);
6575 strcpy (gname
, "None");
6576 glength
= strlen (gname
);
6579 CloseHandle (token
);
6582 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6583 tem
= make_unibyte_string (uname
, ulength
);
6584 attrs
= Fcons (Fcons (Quser
,
6585 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6587 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6588 tem
= make_unibyte_string (gname
, glength
);
6589 attrs
= Fcons (Fcons (Qgroup
,
6590 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6593 if (global_memory_status_ex (&memstex
))
6594 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6595 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6597 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6598 double, so we need to do this for it... */
6600 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6601 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6602 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6604 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6606 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6607 else if (global_memory_status (&memst
))
6608 totphys
= memst
.dwTotalPhys
/ 1024.0;
6611 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6614 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6616 attrs
= Fcons (Fcons (Qmajflt
,
6617 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6619 attrs
= Fcons (Fcons (Qvsize
,
6620 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6622 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6624 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6627 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6629 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6631 attrs
= Fcons (Fcons (Qmajflt
,
6632 make_fixnum_or_float (mem
.PageFaultCount
)),
6634 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6636 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6639 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6641 DWORD rss
= maxrss
/ 1024;
6643 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6645 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6648 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6650 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6651 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6652 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6653 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6654 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6655 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6658 /* FIXME: Retrieve command line by walking the PEB of the process. */
6661 CloseHandle (h_proc
);
6667 /* Wrappers for winsock functions to map between our file descriptors
6668 and winsock's handles; also set h_errno for convenience.
6670 To allow Emacs to run on systems which don't have winsock support
6671 installed, we dynamically link to winsock on startup if present, and
6672 otherwise provide the minimum necessary functionality
6673 (eg. gethostname). */
6675 /* function pointers for relevant socket functions */
6676 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6677 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6678 int (PASCAL
*pfn_WSAGetLastError
) (void);
6679 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6680 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6681 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6682 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6683 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6684 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6685 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6686 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6687 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6688 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6689 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6690 int (PASCAL
*pfn_WSACleanup
) (void);
6692 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6693 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6694 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6695 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6696 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6697 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6698 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6699 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6700 const char * optval
, int optlen
);
6701 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6702 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6704 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6705 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6706 struct sockaddr
* from
, int * fromlen
);
6707 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6708 const struct sockaddr
* to
, int tolen
);
6710 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6711 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6712 #ifndef HANDLE_FLAG_INHERIT
6713 #define HANDLE_FLAG_INHERIT 1
6717 static int winsock_inuse
;
6722 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6724 release_listen_threads ();
6725 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6726 after WSAStartup returns successfully, but it seems reasonable
6727 to allow unloading winsock anyway in that case. */
6728 if (pfn_WSACleanup () == 0 ||
6729 pfn_WSAGetLastError () == WSAENETDOWN
)
6731 if (FreeLibrary (winsock_lib
))
6740 init_winsock (int load_now
)
6742 WSADATA winsockData
;
6744 if (winsock_lib
!= NULL
)
6747 pfn_SetHandleInformation
6748 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6749 "SetHandleInformation");
6751 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6753 if (winsock_lib
!= NULL
)
6755 /* dynamically link to socket functions */
6757 #define LOAD_PROC(fn) \
6758 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6761 LOAD_PROC (WSAStartup
);
6762 LOAD_PROC (WSASetLastError
);
6763 LOAD_PROC (WSAGetLastError
);
6764 LOAD_PROC (WSAEventSelect
);
6765 LOAD_PROC (WSACreateEvent
);
6766 LOAD_PROC (WSACloseEvent
);
6769 LOAD_PROC (connect
);
6770 LOAD_PROC (ioctlsocket
);
6773 LOAD_PROC (closesocket
);
6774 LOAD_PROC (shutdown
);
6777 LOAD_PROC (inet_addr
);
6778 LOAD_PROC (gethostname
);
6779 LOAD_PROC (gethostbyname
);
6780 LOAD_PROC (getservbyname
);
6781 LOAD_PROC (getpeername
);
6782 LOAD_PROC (WSACleanup
);
6783 LOAD_PROC (setsockopt
);
6785 LOAD_PROC (getsockname
);
6787 LOAD_PROC (recvfrom
);
6791 /* specify version 1.1 of winsock */
6792 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6794 if (winsockData
.wVersion
!= 0x101)
6799 /* Report that winsock exists and is usable, but leave
6800 socket functions disabled. I am assuming that calling
6801 WSAStartup does not require any network interaction,
6802 and in particular does not cause or require a dial-up
6803 connection to be established. */
6806 FreeLibrary (winsock_lib
);
6814 FreeLibrary (winsock_lib
);
6824 /* Function to map winsock error codes to errno codes for those errno
6825 code defined in errno.h (errno values not defined by errno.h are
6826 already in nt/inc/sys/socket.h). */
6833 if (winsock_lib
== NULL
)
6836 wsa_err
= pfn_WSAGetLastError ();
6840 case WSAEACCES
: errno
= EACCES
; break;
6841 case WSAEBADF
: errno
= EBADF
; break;
6842 case WSAEFAULT
: errno
= EFAULT
; break;
6843 case WSAEINTR
: errno
= EINTR
; break;
6844 case WSAEINVAL
: errno
= EINVAL
; break;
6845 case WSAEMFILE
: errno
= EMFILE
; break;
6846 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
6847 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
6848 default: errno
= wsa_err
; break;
6856 if (winsock_lib
!= NULL
)
6857 pfn_WSASetLastError (0);
6860 /* Extend strerror to handle the winsock-specific error codes. */
6864 } _wsa_errlist
[] = {
6865 {WSAEINTR
, "Interrupted function call"},
6866 {WSAEBADF
, "Bad file descriptor"},
6867 {WSAEACCES
, "Permission denied"},
6868 {WSAEFAULT
, "Bad address"},
6869 {WSAEINVAL
, "Invalid argument"},
6870 {WSAEMFILE
, "Too many open files"},
6872 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
6873 {WSAEINPROGRESS
, "Operation now in progress"},
6874 {WSAEALREADY
, "Operation already in progress"},
6875 {WSAENOTSOCK
, "Socket operation on non-socket"},
6876 {WSAEDESTADDRREQ
, "Destination address required"},
6877 {WSAEMSGSIZE
, "Message too long"},
6878 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
6879 {WSAENOPROTOOPT
, "Bad protocol option"},
6880 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
6881 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
6882 {WSAEOPNOTSUPP
, "Operation not supported"},
6883 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
6884 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
6885 {WSAEADDRINUSE
, "Address already in use"},
6886 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
6887 {WSAENETDOWN
, "Network is down"},
6888 {WSAENETUNREACH
, "Network is unreachable"},
6889 {WSAENETRESET
, "Network dropped connection on reset"},
6890 {WSAECONNABORTED
, "Software caused connection abort"},
6891 {WSAECONNRESET
, "Connection reset by peer"},
6892 {WSAENOBUFS
, "No buffer space available"},
6893 {WSAEISCONN
, "Socket is already connected"},
6894 {WSAENOTCONN
, "Socket is not connected"},
6895 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
6896 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
6897 {WSAETIMEDOUT
, "Connection timed out"},
6898 {WSAECONNREFUSED
, "Connection refused"},
6899 {WSAELOOP
, "Network loop"}, /* not sure */
6900 {WSAENAMETOOLONG
, "Name is too long"},
6901 {WSAEHOSTDOWN
, "Host is down"},
6902 {WSAEHOSTUNREACH
, "No route to host"},
6903 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
6904 {WSAEPROCLIM
, "Too many processes"},
6905 {WSAEUSERS
, "Too many users"}, /* not sure */
6906 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
6907 {WSAESTALE
, "Data is stale"}, /* not sure */
6908 {WSAEREMOTE
, "Remote error"}, /* not sure */
6910 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
6911 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
6912 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
6913 {WSAEDISCON
, "Graceful shutdown in progress"},
6915 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
6916 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
6917 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
6918 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
6919 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
6920 {WSASYSCALLFAILURE
, "System call failure"},
6921 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
6922 {WSATYPE_NOT_FOUND
, "Class type not found"},
6923 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
6924 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
6925 {WSAEREFUSED
, "Operation refused"}, /* not sure */
6928 {WSAHOST_NOT_FOUND
, "Host not found"},
6929 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
6930 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
6931 {WSANO_DATA
, "Valid name, no data record of requested type"},
6937 sys_strerror (int error_no
)
6940 static char unknown_msg
[40];
6942 if (error_no
>= 0 && error_no
< sys_nerr
)
6943 return sys_errlist
[error_no
];
6945 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
6946 if (_wsa_errlist
[i
].errnum
== error_no
)
6947 return _wsa_errlist
[i
].msg
;
6949 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
6953 /* [andrewi 3-May-96] I've had conflicting results using both methods,
6954 but I believe the method of keeping the socket handle separate (and
6955 insuring it is not inheritable) is the correct one. */
6957 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
6959 static int socket_to_fd (SOCKET s
);
6962 sys_socket (int af
, int type
, int protocol
)
6966 if (winsock_lib
== NULL
)
6969 return INVALID_SOCKET
;
6974 /* call the real socket function */
6975 s
= pfn_socket (af
, type
, protocol
);
6977 if (s
!= INVALID_SOCKET
)
6978 return socket_to_fd (s
);
6984 /* Convert a SOCKET to a file descriptor. */
6986 socket_to_fd (SOCKET s
)
6991 /* Although under NT 3.5 _open_osfhandle will accept a socket
6992 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
6993 that does not work under NT 3.1. However, we can get the same
6994 effect by using a backdoor function to replace an existing
6995 descriptor handle with the one we want. */
6997 /* allocate a file descriptor (with appropriate flags) */
6998 fd
= _open ("NUL:", _O_RDWR
);
7001 /* Make a non-inheritable copy of the socket handle. Note
7002 that it is possible that sockets aren't actually kernel
7003 handles, which appears to be the case on Windows 9x when
7004 the MS Proxy winsock client is installed. */
7006 /* Apparently there is a bug in NT 3.51 with some service
7007 packs, which prevents using DuplicateHandle to make a
7008 socket handle non-inheritable (causes WSACleanup to
7009 hang). The work-around is to use SetHandleInformation
7010 instead if it is available and implemented. */
7011 if (pfn_SetHandleInformation
)
7013 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7017 HANDLE parent
= GetCurrentProcess ();
7018 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7020 if (DuplicateHandle (parent
,
7026 DUPLICATE_SAME_ACCESS
))
7028 /* It is possible that DuplicateHandle succeeds even
7029 though the socket wasn't really a kernel handle,
7030 because a real handle has the same value. So
7031 test whether the new handle really is a socket. */
7032 long nonblocking
= 0;
7033 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7035 pfn_closesocket (s
);
7040 CloseHandle (new_s
);
7045 eassert (fd
< MAXDESC
);
7046 fd_info
[fd
].hnd
= (HANDLE
) s
;
7048 /* set our own internal flags */
7049 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7055 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7057 /* attach child_process to fd_info */
7058 if (fd_info
[ fd
].cp
!= NULL
)
7060 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7064 fd_info
[ fd
].cp
= cp
;
7067 winsock_inuse
++; /* count open sockets */
7075 pfn_closesocket (s
);
7081 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7083 if (winsock_lib
== NULL
)
7086 return SOCKET_ERROR
;
7090 if (fd_info
[s
].flags
& FILE_SOCKET
)
7092 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7093 if (rc
== SOCKET_ERROR
)
7098 return SOCKET_ERROR
;
7102 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7104 if (winsock_lib
== NULL
)
7107 return SOCKET_ERROR
;
7111 if (fd_info
[s
].flags
& FILE_SOCKET
)
7113 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7114 if (rc
== SOCKET_ERROR
)
7119 return SOCKET_ERROR
;
7123 sys_htons (u_short hostshort
)
7125 return (winsock_lib
!= NULL
) ?
7126 pfn_htons (hostshort
) : hostshort
;
7130 sys_ntohs (u_short netshort
)
7132 return (winsock_lib
!= NULL
) ?
7133 pfn_ntohs (netshort
) : netshort
;
7137 sys_inet_addr (const char * cp
)
7139 return (winsock_lib
!= NULL
) ?
7140 pfn_inet_addr (cp
) : INADDR_NONE
;
7144 sys_gethostname (char * name
, int namelen
)
7146 if (winsock_lib
!= NULL
)
7151 retval
= pfn_gethostname (name
, namelen
);
7152 if (retval
== SOCKET_ERROR
)
7157 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7158 return !GetComputerName (name
, (DWORD
*)&namelen
);
7161 return SOCKET_ERROR
;
7165 sys_gethostbyname (const char * name
)
7167 struct hostent
* host
;
7168 int h_err
= h_errno
;
7170 if (winsock_lib
== NULL
)
7172 h_errno
= NO_RECOVERY
;
7178 host
= pfn_gethostbyname (name
);
7190 sys_getservbyname (const char * name
, const char * proto
)
7192 struct servent
* serv
;
7194 if (winsock_lib
== NULL
)
7201 serv
= pfn_getservbyname (name
, proto
);
7208 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7210 if (winsock_lib
== NULL
)
7213 return SOCKET_ERROR
;
7217 if (fd_info
[s
].flags
& FILE_SOCKET
)
7219 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7220 if (rc
== SOCKET_ERROR
)
7225 return SOCKET_ERROR
;
7229 sys_shutdown (int s
, int how
)
7231 if (winsock_lib
== NULL
)
7234 return SOCKET_ERROR
;
7238 if (fd_info
[s
].flags
& FILE_SOCKET
)
7240 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7241 if (rc
== SOCKET_ERROR
)
7246 return SOCKET_ERROR
;
7250 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7252 if (winsock_lib
== NULL
)
7255 return SOCKET_ERROR
;
7259 if (fd_info
[s
].flags
& FILE_SOCKET
)
7261 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7262 (const char *)optval
, optlen
);
7263 if (rc
== SOCKET_ERROR
)
7268 return SOCKET_ERROR
;
7272 sys_listen (int s
, int backlog
)
7274 if (winsock_lib
== NULL
)
7277 return SOCKET_ERROR
;
7281 if (fd_info
[s
].flags
& FILE_SOCKET
)
7283 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7284 if (rc
== SOCKET_ERROR
)
7287 fd_info
[s
].flags
|= FILE_LISTEN
;
7291 return SOCKET_ERROR
;
7295 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7297 if (winsock_lib
== NULL
)
7300 return SOCKET_ERROR
;
7304 if (fd_info
[s
].flags
& FILE_SOCKET
)
7306 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7307 if (rc
== SOCKET_ERROR
)
7312 return SOCKET_ERROR
;
7316 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7318 if (winsock_lib
== NULL
)
7325 if (fd_info
[s
].flags
& FILE_LISTEN
)
7327 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7329 if (t
== INVALID_SOCKET
)
7332 fd
= socket_to_fd (t
);
7336 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7337 ResetEvent (fd_info
[s
].cp
->char_avail
);
7346 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7347 struct sockaddr
* from
, int * fromlen
)
7349 if (winsock_lib
== NULL
)
7352 return SOCKET_ERROR
;
7356 if (fd_info
[s
].flags
& FILE_SOCKET
)
7358 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7359 if (rc
== SOCKET_ERROR
)
7364 return SOCKET_ERROR
;
7368 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7369 const struct sockaddr
* to
, int tolen
)
7371 if (winsock_lib
== NULL
)
7374 return SOCKET_ERROR
;
7378 if (fd_info
[s
].flags
& FILE_SOCKET
)
7380 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7381 if (rc
== SOCKET_ERROR
)
7386 return SOCKET_ERROR
;
7389 /* Windows does not have an fcntl function. Provide an implementation
7390 good enough for Emacs. */
7392 fcntl (int s
, int cmd
, int options
)
7394 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7395 invoked in a context where fd1 is closed and all descriptors less
7396 than fd1 are open, so sys_dup is an adequate implementation. */
7397 if (cmd
== F_DUPFD_CLOEXEC
)
7400 if (winsock_lib
== NULL
)
7407 if (fd_info
[s
].flags
& FILE_SOCKET
)
7409 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7411 unsigned long nblock
= 1;
7412 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7413 if (rc
== SOCKET_ERROR
)
7415 /* Keep track of the fact that we set this to non-blocking. */
7416 fd_info
[s
].flags
|= FILE_NDELAY
;
7422 return SOCKET_ERROR
;
7426 return SOCKET_ERROR
;
7430 /* Shadow main io functions: we need to handle pipes and sockets more
7431 intelligently, and implement non-blocking mode as well. */
7444 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7446 child_process
* cp
= fd_info
[fd
].cp
;
7448 fd_info
[fd
].cp
= NULL
;
7450 if (CHILD_ACTIVE (cp
))
7452 /* if last descriptor to active child_process then cleanup */
7454 for (i
= 0; i
< MAXDESC
; i
++)
7458 if (fd_info
[i
].cp
== cp
)
7463 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7465 if (winsock_lib
== NULL
) emacs_abort ();
7467 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7468 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7470 winsock_inuse
--; /* count open sockets */
7472 /* If the process handle is NULL, it's either a socket
7473 or serial connection, or a subprocess that was
7474 already reaped by reap_subprocess, but whose
7475 resources were not yet freed, because its output was
7476 not fully read yet by the time it was reaped. (This
7477 usually happens with async subprocesses whose output
7478 is being read by Emacs.) Otherwise, this process was
7479 not reaped yet, so we set its FD to a negative value
7480 to make sure sys_select will eventually get to
7481 calling the SIGCHLD handler for it, which will then
7482 invoke waitpid and reap_subprocess. */
7483 if (cp
->procinfo
.hProcess
== NULL
)
7491 if (fd
>= 0 && fd
< MAXDESC
)
7492 fd_info
[fd
].flags
= 0;
7494 /* Note that sockets do not need special treatment here (at least on
7495 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7496 closesocket is equivalent to CloseHandle, which is to be expected
7497 because socket handles are fully fledged kernel handles. */
7509 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7511 /* duplicate our internal info as well */
7512 fd_info
[new_fd
] = fd_info
[fd
];
7518 sys_dup2 (int src
, int dst
)
7522 if (dst
< 0 || dst
>= MAXDESC
)
7528 /* make sure we close the destination first if it's a pipe or socket */
7529 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7532 rc
= _dup2 (src
, dst
);
7535 /* duplicate our internal info as well */
7536 fd_info
[dst
] = fd_info
[src
];
7542 pipe2 (int * phandles
, int pipe2_flags
)
7547 eassert (pipe2_flags
== O_CLOEXEC
);
7549 /* make pipe handles non-inheritable; when we spawn a child, we
7550 replace the relevant handle with an inheritable one. Also put
7551 pipes into binary mode; we will do text mode translation ourselves
7553 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7557 /* Protect against overflow, since Windows can open more handles than
7558 our fd_info array has room for. */
7559 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7561 _close (phandles
[0]);
7562 _close (phandles
[1]);
7568 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7569 fd_info
[phandles
[0]].flags
= flags
;
7571 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7572 fd_info
[phandles
[1]].flags
= flags
;
7579 /* Function to do blocking read of one byte, needed to implement
7580 select. It is only allowed on communication ports, sockets, or
7583 _sys_read_ahead (int fd
)
7588 if (fd
< 0 || fd
>= MAXDESC
)
7589 return STATUS_READ_ERROR
;
7591 cp
= fd_info
[fd
].cp
;
7593 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7594 return STATUS_READ_ERROR
;
7596 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7597 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7599 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7603 cp
->status
= STATUS_READ_IN_PROGRESS
;
7605 if (fd_info
[fd
].flags
& FILE_PIPE
)
7607 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7609 /* Give subprocess time to buffer some more output for us before
7610 reporting that input is available; we need this because Windows 95
7611 connects DOS programs to pipes by making the pipe appear to be
7612 the normal console stdout - as a result most DOS programs will
7613 write to stdout without buffering, ie. one character at a
7614 time. Even some W32 programs do this - "dir" in a command
7615 shell on NT is very slow if we don't do this. */
7618 int wait
= w32_pipe_read_delay
;
7624 /* Yield remainder of our time slice, effectively giving a
7625 temporary priority boost to the child process. */
7629 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7631 HANDLE hnd
= fd_info
[fd
].hnd
;
7632 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7635 /* Configure timeouts for blocking read. */
7636 if (!GetCommTimeouts (hnd
, &ct
))
7638 cp
->status
= STATUS_READ_ERROR
;
7639 return STATUS_READ_ERROR
;
7641 ct
.ReadIntervalTimeout
= 0;
7642 ct
.ReadTotalTimeoutMultiplier
= 0;
7643 ct
.ReadTotalTimeoutConstant
= 0;
7644 if (!SetCommTimeouts (hnd
, &ct
))
7646 cp
->status
= STATUS_READ_ERROR
;
7647 return STATUS_READ_ERROR
;
7650 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7652 if (GetLastError () != ERROR_IO_PENDING
)
7654 cp
->status
= STATUS_READ_ERROR
;
7655 return STATUS_READ_ERROR
;
7657 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7659 cp
->status
= STATUS_READ_ERROR
;
7660 return STATUS_READ_ERROR
;
7664 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7666 unsigned long nblock
= 0;
7667 /* We always want this to block, so temporarily disable NDELAY. */
7668 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7669 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7671 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7673 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7676 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7680 if (rc
== sizeof (char))
7681 cp
->status
= STATUS_READ_SUCCEEDED
;
7683 cp
->status
= STATUS_READ_FAILED
;
7689 _sys_wait_accept (int fd
)
7695 if (fd
< 0 || fd
>= MAXDESC
)
7696 return STATUS_READ_ERROR
;
7698 cp
= fd_info
[fd
].cp
;
7700 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7701 return STATUS_READ_ERROR
;
7703 cp
->status
= STATUS_READ_FAILED
;
7705 hEv
= pfn_WSACreateEvent ();
7706 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7707 if (rc
!= SOCKET_ERROR
)
7710 rc
= WaitForSingleObject (hEv
, 500);
7712 } while (rc
== WAIT_TIMEOUT
7713 && cp
->status
!= STATUS_READ_ERROR
7715 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7716 if (rc
== WAIT_OBJECT_0
)
7717 cp
->status
= STATUS_READ_SUCCEEDED
;
7719 pfn_WSACloseEvent (hEv
);
7725 sys_read (int fd
, char * buffer
, unsigned int count
)
7730 char * orig_buffer
= buffer
;
7738 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7740 child_process
*cp
= fd_info
[fd
].cp
;
7742 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7750 /* re-read CR carried over from last read */
7751 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7753 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7757 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7760 /* presence of a child_process structure means we are operating in
7761 non-blocking mode - otherwise we just call _read directly.
7762 Note that the child_process structure might be missing because
7763 reap_subprocess has been called; in this case the pipe is
7764 already broken, so calling _read on it is okay. */
7767 int current_status
= cp
->status
;
7769 switch (current_status
)
7771 case STATUS_READ_FAILED
:
7772 case STATUS_READ_ERROR
:
7773 /* report normal EOF if nothing in buffer */
7775 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7778 case STATUS_READ_READY
:
7779 case STATUS_READ_IN_PROGRESS
:
7780 DebPrint (("sys_read called when read is in progress\n"));
7781 errno
= EWOULDBLOCK
;
7784 case STATUS_READ_SUCCEEDED
:
7785 /* consume read-ahead char */
7786 *buffer
++ = cp
->chr
;
7789 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7790 ResetEvent (cp
->char_avail
);
7792 case STATUS_READ_ACKNOWLEDGED
:
7796 DebPrint (("sys_read: bad status %d\n", current_status
));
7801 if (fd_info
[fd
].flags
& FILE_PIPE
)
7803 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7804 to_read
= min (waiting
, (DWORD
) count
);
7807 nchars
+= _read (fd
, buffer
, to_read
);
7809 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7811 HANDLE hnd
= fd_info
[fd
].hnd
;
7812 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7818 /* Configure timeouts for non-blocking read. */
7819 if (!GetCommTimeouts (hnd
, &ct
))
7824 ct
.ReadIntervalTimeout
= MAXDWORD
;
7825 ct
.ReadTotalTimeoutMultiplier
= 0;
7826 ct
.ReadTotalTimeoutConstant
= 0;
7827 if (!SetCommTimeouts (hnd
, &ct
))
7833 if (!ResetEvent (ovl
->hEvent
))
7838 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
7840 if (GetLastError () != ERROR_IO_PENDING
)
7845 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7854 else /* FILE_SOCKET */
7856 if (winsock_lib
== NULL
) emacs_abort ();
7858 /* do the equivalent of a non-blocking read */
7859 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
7860 if (waiting
== 0 && nchars
== 0)
7862 errno
= EWOULDBLOCK
;
7868 /* always use binary mode for sockets */
7869 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
7870 if (res
== SOCKET_ERROR
)
7872 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
7873 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
7883 int nread
= _read (fd
, buffer
, count
);
7886 else if (nchars
== 0)
7891 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7892 /* Perform text mode translation if required. */
7893 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7895 nchars
= crlf_to_lf (nchars
, orig_buffer
);
7896 /* If buffer contains only CR, return that. To be absolutely
7897 sure we should attempt to read the next char, but in
7898 practice a CR to be followed by LF would not appear by
7899 itself in the buffer. */
7900 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
7902 fd_info
[fd
].flags
|= FILE_LAST_CR
;
7908 nchars
= _read (fd
, buffer
, count
);
7913 /* From w32xfns.c */
7914 extern HANDLE interrupt_handle
;
7916 /* For now, don't bother with a non-blocking mode */
7918 sys_write (int fd
, const void * buffer
, unsigned int count
)
7928 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7930 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
7936 /* Perform text mode translation if required. */
7937 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7939 char * tmpbuf
= alloca (count
* 2);
7940 unsigned char * src
= (void *)buffer
;
7941 unsigned char * dst
= tmpbuf
;
7946 unsigned char *next
;
7947 /* copy next line or remaining bytes */
7948 next
= _memccpy (dst
, src
, '\n', nbytes
);
7951 /* copied one line ending with '\n' */
7952 int copied
= next
- dst
;
7955 /* insert '\r' before '\n' */
7962 /* copied remaining partial line -> now finished */
7969 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
7971 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
7972 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
7973 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
7976 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
7978 if (GetLastError () != ERROR_IO_PENDING
)
7983 if (detect_input_pending ())
7984 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
7987 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
7988 if (active
== WAIT_OBJECT_0
)
7989 { /* User pressed C-g, cancel write, then leave. Don't bother
7990 cleaning up as we may only get stuck in buggy drivers. */
7991 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
7996 if (active
== WAIT_OBJECT_0
+ 1
7997 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8004 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8006 unsigned long nblock
= 0;
8007 if (winsock_lib
== NULL
) emacs_abort ();
8009 /* TODO: implement select() properly so non-blocking I/O works. */
8010 /* For now, make sure the write blocks. */
8011 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8012 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8014 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8016 /* Set the socket back to non-blocking if it was before,
8017 for other operations that support it. */
8018 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8021 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8024 if (nchars
== SOCKET_ERROR
)
8026 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8027 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8033 /* Some networked filesystems don't like too large writes, so
8034 break them into smaller chunks. See the Comments section of
8035 the MSDN documentation of WriteFile for details behind the
8036 choice of the value of CHUNK below. See also the thread
8037 http://thread.gmane.org/gmane.comp.version-control.git/145294
8038 in the git mailing list. */
8039 const unsigned char *p
= buffer
;
8040 const unsigned chunk
= 30 * 1024 * 1024;
8045 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8046 int n
= _write (fd
, p
, this_chunk
);
8054 else if (n
< this_chunk
)
8065 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8067 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8069 /* Return information about network interface IFNAME, or about all
8070 interfaces (if IFNAME is nil). */
8072 network_interface_get_info (Lisp_Object ifname
)
8074 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8075 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8076 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8077 Lisp_Object res
= Qnil
;
8079 if (retval
== ERROR_BUFFER_OVERFLOW
)
8081 ainfo
= xrealloc (ainfo
, ainfo_len
);
8082 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8085 if (retval
== ERROR_SUCCESS
)
8087 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8088 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8090 struct sockaddr_in sa
;
8092 /* For the below, we need some winsock functions, so make sure
8093 the winsock DLL is loaded. If we cannot successfully load
8094 it, they will have no use of the information we provide,
8096 if (!winsock_lib
&& !init_winsock (1))
8099 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8101 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8103 /* Present Unix-compatible interface names, instead of the
8104 Windows names, which are really GUIDs not readable by
8106 static const char *ifmt
[] = {
8107 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8122 switch (adapter
->Type
)
8124 case MIB_IF_TYPE_ETHERNET
:
8125 /* Windows before Vista reports wireless adapters as
8126 Ethernet. Work around by looking at the Description
8128 if (strstr (adapter
->Description
, "Wireless "))
8131 if_num
= wlan_count
++;
8135 ifmt_idx
= ETHERNET
;
8136 if_num
= eth_count
++;
8139 case MIB_IF_TYPE_TOKENRING
:
8140 ifmt_idx
= TOKENRING
;
8141 if_num
= tr_count
++;
8143 case MIB_IF_TYPE_FDDI
:
8145 if_num
= fddi_count
++;
8147 case MIB_IF_TYPE_PPP
:
8149 if_num
= ppp_count
++;
8151 case MIB_IF_TYPE_SLIP
:
8153 if_num
= sl_count
++;
8155 case IF_TYPE_IEEE80211
:
8157 if_num
= wlan_count
++;
8159 case MIB_IF_TYPE_LOOPBACK
:
8162 ifmt_idx
= LOOPBACK
;
8163 if_num
= lo_count
++;
8169 ifmt_idx
= OTHER_IF
;
8170 if_num
= ifx_count
++;
8173 if (ifmt_idx
== NONE
)
8175 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8177 sa
.sin_family
= AF_INET
;
8178 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8179 if (ip_addr
== INADDR_NONE
)
8181 /* Bogus address, skip this interface. */
8184 sa
.sin_addr
.s_addr
= ip_addr
;
8187 res
= Fcons (Fcons (build_string (namebuf
),
8188 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8189 sizeof (struct sockaddr
))),
8191 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8193 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8194 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8195 Lisp_Object flags
= Qnil
;
8199 /* Flags. We guess most of them by type, since the
8200 Windows flags are different and hard to get by. */
8201 flags
= Fcons (intern ("up"), flags
);
8202 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8204 flags
= Fcons (intern ("broadcast"), flags
);
8205 flags
= Fcons (intern ("multicast"), flags
);
8207 flags
= Fcons (intern ("running"), flags
);
8208 if (ifmt_idx
== PPP
)
8210 flags
= Fcons (intern ("pointopoint"), flags
);
8211 flags
= Fcons (intern ("noarp"), flags
);
8213 if (adapter
->HaveWins
)
8214 flags
= Fcons (intern ("WINS"), flags
);
8215 if (adapter
->DhcpEnabled
)
8216 flags
= Fcons (intern ("dynamic"), flags
);
8218 res
= Fcons (flags
, res
);
8220 /* Hardware address and its family. */
8221 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8222 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8223 /* Windows does not support AF_LINK or AF_PACKET family
8224 of addresses. Use an arbitrary family number that is
8225 identical to what GNU/Linux returns. */
8226 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8229 sa
.sin_family
= AF_INET
;
8230 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8231 if (net_mask
!= INADDR_NONE
)
8233 sa
.sin_addr
.s_addr
= net_mask
;
8235 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8236 sizeof (struct sockaddr
)),
8240 res
= Fcons (Qnil
, res
);
8242 sa
.sin_family
= AF_INET
;
8243 if (ip_addr
!= INADDR_NONE
)
8245 /* Broadcast address is only reported by
8246 GetAdaptersAddresses, which is of limited
8247 availability. Generate it on our own. */
8248 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8250 sa
.sin_addr
.s_addr
= bcast_addr
;
8252 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8253 sizeof (struct sockaddr
)),
8257 sa
.sin_addr
.s_addr
= ip_addr
;
8259 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8260 sizeof (struct sockaddr
)),
8264 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8267 /* GetAdaptersInfo is documented to not report loopback
8268 interfaces, so we generate one out of thin air. */
8271 sa
.sin_family
= AF_INET
;
8275 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8276 res
= Fcons (Fcons (build_string ("lo"),
8277 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8278 sizeof (struct sockaddr
))),
8281 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8283 res
= Fcons (Fcons (intern ("running"),
8284 Fcons (intern ("loopback"),
8285 Fcons (intern ("up"), Qnil
))), Qnil
);
8286 /* 772 is what 3 different GNU/Linux systems report for
8287 the loopback interface. */
8288 res
= Fcons (Fcons (make_number (772),
8289 Fmake_vector (make_number (6),
8292 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8293 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8294 sizeof (struct sockaddr
)),
8296 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8297 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8298 sizeof (struct sockaddr
)),
8300 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8301 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8302 sizeof (struct sockaddr
)),
8315 network_interface_list (void)
8317 return network_interface_get_info (Qnil
);
8321 network_interface_info (Lisp_Object ifname
)
8323 return network_interface_get_info (ifname
);
8327 /* The Windows CRT functions are "optimized for speed", so they don't
8328 check for timezone and DST changes if they were last called less
8329 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8330 all Emacs features that repeatedly call time functions (e.g.,
8331 display-time) are in real danger of missing timezone and DST
8332 changes. Calling tzset before each localtime call fixes that. */
8334 sys_localtime (const time_t *t
)
8337 return localtime (t
);
8342 /* Try loading LIBRARY_ID from the file(s) specified in
8343 Vdynamic_library_alist. If the library is loaded successfully,
8344 return the handle of the DLL, and record the filename in the
8345 property :loaded-from of LIBRARY_ID. If the library could not be
8346 found, or when it was already loaded (because the handle is not
8347 recorded anywhere, and so is lost after use), return NULL.
8349 We could also save the handle in :loaded-from, but currently
8350 there's no use case for it. */
8352 w32_delayed_load (Lisp_Object library_id
)
8354 HMODULE dll_handle
= NULL
;
8356 CHECK_SYMBOL (library_id
);
8358 if (CONSP (Vdynamic_library_alist
)
8359 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8361 Lisp_Object found
= Qnil
;
8362 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8365 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8367 Lisp_Object dll
= XCAR (dlls
);
8368 char name
[MAX_UTF8_PATH
];
8372 dll
= ENCODE_FILE (dll
);
8373 if (w32_unicode_filenames
)
8375 wchar_t name_w
[MAX_PATH
];
8377 filename_to_utf16 (SSDATA (dll
), name_w
);
8378 dll_handle
= LoadLibraryW (name_w
);
8381 res
= GetModuleFileNameW (dll_handle
, name_w
,
8384 filename_from_utf16 (name_w
, name
);
8389 char name_a
[MAX_PATH
];
8391 filename_to_ansi (SSDATA (dll
), name_a
);
8392 dll_handle
= LoadLibraryA (name_a
);
8395 res
= GetModuleFileNameA (dll_handle
, name_a
,
8398 filename_from_ansi (name_a
, name
);
8403 ptrdiff_t len
= strlen (name
);
8406 /* Possibly truncated */
8407 ? make_specified_string (name
, -1, len
, 1)
8413 Fput (library_id
, QCloaded_from
, found
);
8421 check_windows_init_file (void)
8423 /* A common indication that Emacs is not installed properly is when
8424 it cannot find the Windows installation file. If this file does
8425 not exist in the expected place, tell the user. */
8427 if (!noninteractive
&& !inhibit_window_system
8428 /* Vload_path is not yet initialized when we are loading
8430 && NILP (Vpurify_flag
))
8432 Lisp_Object init_file
;
8435 /* Implementation note: this function runs early during Emacs
8436 startup, before startup.el is run. So Vload_path is still in
8437 its initial unibyte form, holding ANSI-encoded file names.
8438 That is why we never bother to ENCODE_FILE here, nor use wide
8439 APIs for file names: we will never get UTF-8 encoded file
8441 init_file
= build_string ("term/w32-win");
8442 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
8445 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8446 char *init_file_name
= SDATA (init_file
);
8447 char *load_path
= SDATA (load_path_print
);
8448 char *buffer
= alloca (1024
8449 + strlen (init_file_name
)
8450 + strlen (load_path
));
8453 "The Emacs Windows initialization file \"%s.el\" "
8454 "could not be found in your Emacs installation. "
8455 "Emacs checked the following directories for this file:\n"
8457 "When Emacs cannot find this file, it usually means that it "
8458 "was not installed properly, or its distribution file was "
8459 "not unpacked properly.\nSee the README.W32 file in the "
8460 "top-level Emacs directory for more information.",
8461 init_file_name
, load_path
);
8464 "Emacs Abort Dialog",
8465 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8466 /* Use the low-level system abort. */
8477 term_ntproc (int ignored
)
8483 /* shutdown the socket interface if necessary */
8490 init_ntproc (int dumping
)
8492 sigset_t initial_mask
= 0;
8494 /* Initialize the socket interface now if available and requested by
8495 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8496 delayed until open-network-stream is called (w32-has-winsock can
8497 also be used to dynamically load or reload winsock).
8499 Conveniently, init_environment is called before us, so
8500 PRELOAD_WINSOCK can be set in the registry. */
8502 /* Always initialize this correctly. */
8505 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8506 init_winsock (TRUE
);
8508 /* Initial preparation for subprocess support: replace our standard
8509 handles with non-inheritable versions. */
8512 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8513 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8514 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8516 parent
= GetCurrentProcess ();
8518 /* ignore errors when duplicating and closing; typically the
8519 handles will be invalid when running as a gui program. */
8520 DuplicateHandle (parent
,
8521 GetStdHandle (STD_INPUT_HANDLE
),
8526 DUPLICATE_SAME_ACCESS
);
8528 DuplicateHandle (parent
,
8529 GetStdHandle (STD_OUTPUT_HANDLE
),
8534 DUPLICATE_SAME_ACCESS
);
8536 DuplicateHandle (parent
,
8537 GetStdHandle (STD_ERROR_HANDLE
),
8542 DUPLICATE_SAME_ACCESS
);
8548 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8549 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8551 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8554 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8555 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8557 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8560 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8561 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8563 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8567 /* unfortunately, atexit depends on implementation of malloc */
8568 /* atexit (term_ntproc); */
8571 /* Make sure we start with all signals unblocked. */
8572 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8573 signal (SIGABRT
, term_ntproc
);
8577 /* determine which drives are fixed, for GetCachedVolumeInformation */
8579 /* GetDriveType must have trailing backslash. */
8580 char drive
[] = "A:\\";
8582 /* Loop over all possible drive letters */
8583 while (*drive
<= 'Z')
8585 /* Record if this drive letter refers to a fixed drive. */
8586 fixed_drives
[DRIVE_INDEX (*drive
)] =
8587 (GetDriveType (drive
) == DRIVE_FIXED
);
8592 /* Reset the volume info cache. */
8593 volume_cache
= NULL
;
8598 shutdown_handler ensures that buffers' autosave files are
8599 up to date when the user logs off, or the system shuts down.
8602 shutdown_handler (DWORD type
)
8604 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8605 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8606 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8607 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8609 /* Shut down cleanly, making sure autosave files are up to date. */
8610 shut_down_emacs (0, Qnil
);
8613 /* Allow other handlers to handle this signal. */
8618 globals_of_w32 is used to initialize those global variables that
8619 must always be initialized on startup even when the global variable
8620 initialized is non zero (see the function main in emacs.c).
8623 globals_of_w32 (void)
8625 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8627 get_process_times_fn
= (GetProcessTimes_Proc
)
8628 GetProcAddress (kernel32
, "GetProcessTimes");
8630 DEFSYM (QCloaded_from
, ":loaded-from");
8632 g_b_init_is_windows_9x
= 0;
8633 g_b_init_open_process_token
= 0;
8634 g_b_init_get_token_information
= 0;
8635 g_b_init_lookup_account_sid
= 0;
8636 g_b_init_get_sid_sub_authority
= 0;
8637 g_b_init_get_sid_sub_authority_count
= 0;
8638 g_b_init_get_security_info
= 0;
8639 g_b_init_get_file_security_w
= 0;
8640 g_b_init_get_file_security_a
= 0;
8641 g_b_init_get_security_descriptor_owner
= 0;
8642 g_b_init_get_security_descriptor_group
= 0;
8643 g_b_init_is_valid_sid
= 0;
8644 g_b_init_create_toolhelp32_snapshot
= 0;
8645 g_b_init_process32_first
= 0;
8646 g_b_init_process32_next
= 0;
8647 g_b_init_open_thread_token
= 0;
8648 g_b_init_impersonate_self
= 0;
8649 g_b_init_revert_to_self
= 0;
8650 g_b_init_get_process_memory_info
= 0;
8651 g_b_init_get_process_working_set_size
= 0;
8652 g_b_init_global_memory_status
= 0;
8653 g_b_init_global_memory_status_ex
= 0;
8654 g_b_init_equal_sid
= 0;
8655 g_b_init_copy_sid
= 0;
8656 g_b_init_get_length_sid
= 0;
8657 g_b_init_get_native_system_info
= 0;
8658 g_b_init_get_system_times
= 0;
8659 g_b_init_create_symbolic_link_w
= 0;
8660 g_b_init_create_symbolic_link_a
= 0;
8661 g_b_init_get_security_descriptor_dacl
= 0;
8662 g_b_init_convert_sd_to_sddl
= 0;
8663 g_b_init_convert_sddl_to_sd
= 0;
8664 g_b_init_is_valid_security_descriptor
= 0;
8665 g_b_init_set_file_security_w
= 0;
8666 g_b_init_set_file_security_a
= 0;
8667 g_b_init_get_adapters_info
= 0;
8668 num_of_processors
= 0;
8669 /* The following sets a handler for shutdown notifications for
8670 console apps. This actually applies to Emacs in both console and
8671 GUI modes, since we had to fool windows into thinking emacs is a
8672 console application to get console mode to work. */
8673 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8675 /* "None" is the default group name on standalone workstations. */
8676 strcpy (dflt_group_name
, "None");
8678 /* Reset, in case it has some value inherited from dump time. */
8679 w32_stat_get_owner_group
= 0;
8681 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8682 (a.k.a. "wide") APIs to invoke functions that accept file
8684 if (is_windows_9x ())
8685 w32_unicode_filenames
= 0;
8687 w32_unicode_filenames
= 1;
8690 /* For make-serial-process */
8692 serial_open (Lisp_Object port_obj
)
8694 char *port
= SSDATA (port_obj
);
8699 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8700 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8701 if (hnd
== INVALID_HANDLE_VALUE
)
8702 error ("Could not open %s", port
);
8703 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8705 error ("Could not open %s", port
);
8709 error ("Could not create child process");
8711 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8712 fd_info
[ fd
].hnd
= hnd
;
8713 fd_info
[ fd
].flags
|=
8714 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8715 if (fd_info
[ fd
].cp
!= NULL
)
8717 error ("fd_info[fd = %d] is already in use", fd
);
8719 fd_info
[ fd
].cp
= cp
;
8720 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8721 if (cp
->ovl_read
.hEvent
== NULL
)
8722 error ("Could not create read event");
8723 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8724 if (cp
->ovl_write
.hEvent
== NULL
)
8725 error ("Could not create write event");
8730 /* For serial-process-configure */
8732 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8734 Lisp_Object childp2
= Qnil
;
8735 Lisp_Object tem
= Qnil
;
8739 char summary
[4] = "???"; /* This usually becomes "8N1". */
8741 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8742 error ("Not a serial process");
8743 hnd
= fd_info
[ p
->outfd
].hnd
;
8745 childp2
= Fcopy_sequence (p
->childp
);
8747 /* Initialize timeouts for blocking read and blocking write. */
8748 if (!GetCommTimeouts (hnd
, &ct
))
8749 error ("GetCommTimeouts() failed");
8750 ct
.ReadIntervalTimeout
= 0;
8751 ct
.ReadTotalTimeoutMultiplier
= 0;
8752 ct
.ReadTotalTimeoutConstant
= 0;
8753 ct
.WriteTotalTimeoutMultiplier
= 0;
8754 ct
.WriteTotalTimeoutConstant
= 0;
8755 if (!SetCommTimeouts (hnd
, &ct
))
8756 error ("SetCommTimeouts() failed");
8757 /* Read port attributes and prepare default configuration. */
8758 memset (&dcb
, 0, sizeof (dcb
));
8759 dcb
.DCBlength
= sizeof (DCB
);
8760 if (!GetCommState (hnd
, &dcb
))
8761 error ("GetCommState() failed");
8764 dcb
.fAbortOnError
= FALSE
;
8765 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8770 /* Configure speed. */
8771 if (!NILP (Fplist_member (contact
, QCspeed
)))
8772 tem
= Fplist_get (contact
, QCspeed
);
8774 tem
= Fplist_get (p
->childp
, QCspeed
);
8776 dcb
.BaudRate
= XINT (tem
);
8777 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8779 /* Configure bytesize. */
8780 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8781 tem
= Fplist_get (contact
, QCbytesize
);
8783 tem
= Fplist_get (p
->childp
, QCbytesize
);
8785 tem
= make_number (8);
8787 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8788 error (":bytesize must be nil (8), 7, or 8");
8789 dcb
.ByteSize
= XINT (tem
);
8790 summary
[0] = XINT (tem
) + '0';
8791 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8793 /* Configure parity. */
8794 if (!NILP (Fplist_member (contact
, QCparity
)))
8795 tem
= Fplist_get (contact
, QCparity
);
8797 tem
= Fplist_get (p
->childp
, QCparity
);
8798 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8799 error (":parity must be nil (no parity), `even', or `odd'");
8800 dcb
.fParity
= FALSE
;
8801 dcb
.Parity
= NOPARITY
;
8802 dcb
.fErrorChar
= FALSE
;
8807 else if (EQ (tem
, Qeven
))
8811 dcb
.Parity
= EVENPARITY
;
8812 dcb
.fErrorChar
= TRUE
;
8814 else if (EQ (tem
, Qodd
))
8818 dcb
.Parity
= ODDPARITY
;
8819 dcb
.fErrorChar
= TRUE
;
8821 childp2
= Fplist_put (childp2
, QCparity
, tem
);
8823 /* Configure stopbits. */
8824 if (!NILP (Fplist_member (contact
, QCstopbits
)))
8825 tem
= Fplist_get (contact
, QCstopbits
);
8827 tem
= Fplist_get (p
->childp
, QCstopbits
);
8829 tem
= make_number (1);
8831 if (XINT (tem
) != 1 && XINT (tem
) != 2)
8832 error (":stopbits must be nil (1 stopbit), 1, or 2");
8833 summary
[2] = XINT (tem
) + '0';
8834 if (XINT (tem
) == 1)
8835 dcb
.StopBits
= ONESTOPBIT
;
8836 else if (XINT (tem
) == 2)
8837 dcb
.StopBits
= TWOSTOPBITS
;
8838 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
8840 /* Configure flowcontrol. */
8841 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
8842 tem
= Fplist_get (contact
, QCflowcontrol
);
8844 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
8845 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
8846 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
8847 dcb
.fOutxCtsFlow
= FALSE
;
8848 dcb
.fOutxDsrFlow
= FALSE
;
8849 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
8850 dcb
.fDsrSensitivity
= FALSE
;
8851 dcb
.fTXContinueOnXoff
= FALSE
;
8854 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
8855 dcb
.XonChar
= 17; /* Control-Q */
8856 dcb
.XoffChar
= 19; /* Control-S */
8859 /* Already configured. */
8861 else if (EQ (tem
, Qhw
))
8863 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
8864 dcb
.fOutxCtsFlow
= TRUE
;
8866 else if (EQ (tem
, Qsw
))
8871 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
8873 /* Activate configuration. */
8874 if (!SetCommState (hnd
, &dcb
))
8875 error ("SetCommState() failed");
8877 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
8878 pset_childp (p
, childp2
);
8884 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
8888 struct timespec timeout
;
8889 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8890 int fd
= process
->infd
;
8892 n
= sys_read (fd
, (char*)buf
, sz
);
8899 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8900 if (err
== EWOULDBLOCK
)
8903 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
8909 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
8911 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8912 int fd
= process
->outfd
;
8913 ssize_t n
= sys_write (fd
, buf
, sz
);
8915 /* 0 or more bytes written means everything went fine. */
8919 /* Negative bytes written means we got an error in errno.
8920 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8921 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
8922 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
8926 #endif /* HAVE_GNUTLS */