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 and
1339 . Lisp code that encodes or decodes file names manually should
1340 normally use 'utf-8' as the coding-system on Windows,
1341 disregarding file-name-coding-system. This is a somewhat
1342 unpleasant consequence, but it cannot be avoided. Fortunately,
1343 very few Lisp packages need to do that.
1345 More generally, passing to library functions (e.g., fopen or
1346 opendir) file names already encoded in the ANSI codepage is
1347 explictly *verboten*, as all those functions, as shadowed and
1348 emulated here, assume they will receive UTF-8 encoded file names.
1350 For the same reasons, no CRT function or Win32 API can be called
1351 directly in Emacs sources, without either converting the file
1352 name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
1353 through some shadowing function defined here.
1355 . Environment variables stored in Vprocess_environment are encoded
1356 in the ANSI codepage, so if getenv/egetenv is used for a variable
1357 whose value is a file name or a list of directories, it needs to
1358 be converted to UTF-8, before it is used as argument to functions
1359 or decoded into a Lisp string.
1361 . File names passed to external libraries, like the image libraries
1362 and GnuTLS, need special handling. These libraries generally
1363 don't support UTF-16 or UTF-8 file names, so they must get file
1364 names encoded in the ANSI codepage. To facilitate using these
1365 libraries with file names that are not encodable in the ANSI
1366 codepage, use the function ansi_encode_filename, which will try
1367 to use the short 8+3 alias of a file name if that file name is
1368 not encodable in the ANSI codepage. See image.c and gnutls.c for
1369 examples of how this should be done.
1371 . Running subprocesses in non-ASCII directories and with non-ASCII
1372 file arguments is limited to the current codepage (even though
1373 Emacs is perfectly capable of finding an executable program file
1374 even in a directory whose name cannot be encoded in the curreent
1375 codepage). This is because the command-line arguments are
1376 encoded _before_ they get to the w32-specific level, and the
1377 encoding is not known in advance (it doesn't have to be the
1378 current ANSI codepage), so w32proc.c functions cannot re-encode
1379 them in UTF-16. This should be fixed, but will also require
1380 changes in cmdproxy. The current limitation is not terribly bad
1381 anyway, since very few, if any, Windows console programs that are
1382 likely to be invoked by Emacs support UTF-16 encoded command
1385 . For similar reasons, server.el and emacsclient are also limited
1386 to the current ANSI codepage for now.
1388 . Emacs itself can only handle command-line arguments encoded in
1389 the current codepage.
1391 . Turning on w32-unicode-filename on Windows 9X (if it at all
1392 works) requires UNICOWS.DLL, which is currently loaded only in a
1397 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1398 codepage defined by file-name-coding-system. */
1400 /* Current codepage for encoding file names. */
1401 static int file_name_codepage
;
1403 /* Produce a Windows ANSI codepage suitable for encoding file names.
1404 Return the information about that codepage in CP_INFO. */
1406 codepage_for_filenames (CPINFO
*cp_info
)
1408 /* A simple cache to avoid calling GetCPInfo every time we need to
1409 encode/decode a file name. The file-name encoding is not
1410 supposed to be changed too frequently, if ever. */
1411 static Lisp_Object last_file_name_encoding
;
1413 Lisp_Object current_encoding
;
1415 current_encoding
= Vfile_name_coding_system
;
1416 if (NILP (current_encoding
))
1417 current_encoding
= Vdefault_file_name_coding_system
;
1419 if (!EQ (last_file_name_encoding
, current_encoding
))
1421 /* Default to the current ANSI codepage. */
1422 file_name_codepage
= w32_ansi_code_page
;
1424 if (NILP (current_encoding
))
1426 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1427 char *cp
= NULL
, *end
;
1430 if (strncmp (cpname
, "cp", 2) == 0)
1432 else if (strncmp (cpname
, "windows-", 8) == 0)
1438 cpnum
= strtol (cp
, &end
, 10);
1439 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1440 file_name_codepage
= cpnum
;
1444 if (!file_name_codepage
)
1445 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1447 if (!GetCPInfo (file_name_codepage
, &cp
))
1449 file_name_codepage
= CP_ACP
;
1450 if (!GetCPInfo (file_name_codepage
, &cp
))
1457 return file_name_codepage
;
1461 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1463 int result
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1468 DWORD err
= GetLastError ();
1472 case ERROR_INVALID_FLAGS
:
1473 case ERROR_INVALID_PARAMETER
:
1476 case ERROR_INSUFFICIENT_BUFFER
:
1477 case ERROR_NO_UNICODE_TRANSLATION
:
1488 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1490 int result
= WideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1491 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1495 DWORD err
= GetLastError ();
1499 case ERROR_INVALID_FLAGS
:
1500 case ERROR_INVALID_PARAMETER
:
1503 case ERROR_INSUFFICIENT_BUFFER
:
1504 case ERROR_NO_UNICODE_TRANSLATION
:
1515 filename_to_ansi (const char *fn_in
, char *fn_out
)
1517 wchar_t fn_utf16
[MAX_PATH
];
1519 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1522 int codepage
= codepage_for_filenames (NULL
);
1524 result
= WideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1525 fn_out
, MAX_PATH
, NULL
, NULL
);
1528 DWORD err
= GetLastError ();
1532 case ERROR_INVALID_FLAGS
:
1533 case ERROR_INVALID_PARAMETER
:
1536 case ERROR_INSUFFICIENT_BUFFER
:
1537 case ERROR_NO_UNICODE_TRANSLATION
:
1550 filename_from_ansi (const char *fn_in
, char *fn_out
)
1552 wchar_t fn_utf16
[MAX_PATH
];
1553 int codepage
= codepage_for_filenames (NULL
);
1554 int result
= MultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1555 fn_utf16
, MAX_PATH
);
1559 DWORD err
= GetLastError ();
1563 case ERROR_INVALID_FLAGS
:
1564 case ERROR_INVALID_PARAMETER
:
1567 case ERROR_INSUFFICIENT_BUFFER
:
1568 case ERROR_NO_UNICODE_TRANSLATION
:
1575 return filename_from_utf16 (fn_utf16
, fn_out
);
1580 /* The directory where we started, in UTF-8. */
1581 static char startup_dir
[MAX_UTF8_PATH
];
1583 /* Get the current working directory. */
1585 getcwd (char *dir
, int dirsize
)
1592 if (dirsize
<= strlen (startup_dir
))
1598 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1602 /* Emacs doesn't actually change directory itself, it stays in the
1603 same directory where it was started. */
1604 strcpy (dir
, startup_dir
);
1609 /* Emulate getloadavg. */
1611 struct load_sample
{
1618 /* Number of processors on this machine. */
1619 static unsigned num_of_processors
;
1621 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1622 static struct load_sample samples
[16*60];
1623 static int first_idx
= -1, last_idx
= -1;
1624 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1629 int next_idx
= from
+ 1;
1631 if (next_idx
>= max_idx
)
1640 int prev_idx
= from
- 1;
1643 prev_idx
= max_idx
- 1;
1649 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1651 SYSTEM_INFO sysinfo
;
1652 FILETIME ft_idle
, ft_user
, ft_kernel
;
1654 /* Initialize the number of processors on this machine. */
1655 if (num_of_processors
<= 0)
1657 get_native_system_info (&sysinfo
);
1658 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1659 if (num_of_processors
<= 0)
1661 GetSystemInfo (&sysinfo
);
1662 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1664 if (num_of_processors
<= 0)
1665 num_of_processors
= 1;
1668 /* TODO: Take into account threads that are ready to run, by
1669 sampling the "\System\Processor Queue Length" performance
1670 counter. The code below accounts only for threads that are
1671 actually running. */
1673 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1675 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1677 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1678 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1679 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1680 *idle
= uidle
.QuadPart
;
1681 *kernel
= ukernel
.QuadPart
;
1682 *user
= uuser
.QuadPart
;
1692 /* Produce the load average for a given time interval, using the
1693 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1694 1-minute, 5-minute, or 15-minute average, respectively. */
1698 double retval
= -1.0;
1701 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1702 time_t now
= samples
[last_idx
].sample_time
;
1704 if (first_idx
!= last_idx
)
1706 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1708 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1709 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1712 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1713 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1714 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1716 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1719 if (idx
== first_idx
)
1728 getloadavg (double loadavg
[], int nelem
)
1731 ULONGLONG idle
, kernel
, user
;
1732 time_t now
= time (NULL
);
1734 /* Store another sample. We ignore samples that are less than 1 sec
1736 if (difftime (now
, samples
[last_idx
].sample_time
) >= 1.0 - 2*DBL_EPSILON
*now
)
1738 sample_system_load (&idle
, &kernel
, &user
);
1739 last_idx
= buf_next (last_idx
);
1740 samples
[last_idx
].sample_time
= now
;
1741 samples
[last_idx
].idle
= idle
;
1742 samples
[last_idx
].kernel
= kernel
;
1743 samples
[last_idx
].user
= user
;
1744 /* If the buffer has more that 15 min worth of samples, discard
1746 if (first_idx
== -1)
1747 first_idx
= last_idx
;
1748 while (first_idx
!= last_idx
1749 && (difftime (now
, samples
[first_idx
].sample_time
)
1750 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1751 first_idx
= buf_next (first_idx
);
1754 for (elem
= 0; elem
< nelem
; elem
++)
1756 double avg
= getavg (elem
);
1760 loadavg
[elem
] = avg
;
1766 /* Emulate getpwuid, getpwnam and others. */
1768 #define PASSWD_FIELD_SIZE 256
1770 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1771 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1772 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1773 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1774 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1776 static struct passwd dflt_passwd
=
1788 static char dflt_group_name
[GNLEN
+1];
1790 static struct group dflt_group
=
1792 /* When group information is not available, we return this as the
1793 group for all files. */
1801 return dflt_passwd
.pw_uid
;
1807 /* I could imagine arguing for checking to see whether the user is
1808 in the Administrators group and returning a UID of 0 for that
1809 case, but I don't know how wise that would be in the long run. */
1816 return dflt_passwd
.pw_gid
;
1826 getpwuid (unsigned uid
)
1828 if (uid
== dflt_passwd
.pw_uid
)
1829 return &dflt_passwd
;
1834 getgrgid (gid_t gid
)
1840 getpwnam (char *name
)
1844 pw
= getpwuid (getuid ());
1848 if (xstrcasecmp (name
, pw
->pw_name
))
1855 init_user_info (void)
1857 /* Find the user's real name by opening the process token and
1858 looking up the name associated with the user-sid in that token.
1860 Use the relative portion of the identifier authority value from
1861 the user-sid as the user id value (same for group id using the
1862 primary group sid from the process token). */
1864 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1865 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1866 DWORD glength
= sizeof (gname
);
1867 HANDLE token
= NULL
;
1868 SID_NAME_USE user_type
;
1869 unsigned char *buf
= NULL
;
1871 TOKEN_USER user_token
;
1872 TOKEN_PRIMARY_GROUP group_token
;
1875 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1878 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1879 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1881 buf
= xmalloc (blen
);
1882 result
= get_token_information (token
, TokenUser
,
1883 (LPVOID
)buf
, blen
, &needed
);
1886 memcpy (&user_token
, buf
, sizeof (user_token
));
1887 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1889 domain
, &dlength
, &user_type
);
1897 strcpy (dflt_passwd
.pw_name
, uname
);
1898 /* Determine a reasonable uid value. */
1899 if (xstrcasecmp ("administrator", uname
) == 0)
1901 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
1902 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
1906 /* Use the last sub-authority value of the RID, the relative
1907 portion of the SID, as user/group ID. */
1908 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
1910 /* Get group id and name. */
1911 result
= get_token_information (token
, TokenPrimaryGroup
,
1912 (LPVOID
)buf
, blen
, &needed
);
1913 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1915 buf
= xrealloc (buf
, blen
= needed
);
1916 result
= get_token_information (token
, TokenPrimaryGroup
,
1917 (LPVOID
)buf
, blen
, &needed
);
1921 memcpy (&group_token
, buf
, sizeof (group_token
));
1922 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
1923 dlength
= sizeof (domain
);
1924 /* If we can get at the real Primary Group name, use that.
1925 Otherwise, the default group name was already set to
1926 "None" in globals_of_w32. */
1927 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
1928 gname
, &glength
, NULL
, &dlength
,
1930 strcpy (dflt_group_name
, gname
);
1933 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1936 /* If security calls are not supported (presumably because we
1937 are running under Windows 9X), fallback to this: */
1938 else if (GetUserName (uname
, &ulength
))
1940 strcpy (dflt_passwd
.pw_name
, uname
);
1941 if (xstrcasecmp ("administrator", uname
) == 0)
1942 dflt_passwd
.pw_uid
= 0;
1944 dflt_passwd
.pw_uid
= 123;
1945 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1949 strcpy (dflt_passwd
.pw_name
, "unknown");
1950 dflt_passwd
.pw_uid
= 123;
1951 dflt_passwd
.pw_gid
= 123;
1953 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
1955 /* Set dir and shell from environment variables. */
1956 if (w32_unicode_filenames
)
1958 wchar_t *home
= _wgetenv (L
"HOME");
1959 wchar_t *shell
= _wgetenv (L
"SHELL");
1961 /* Ensure HOME and SHELL are defined. */
1966 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
1967 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
1971 char *home
= getenv ("HOME");
1972 char *shell
= getenv ("SHELL");
1978 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
1979 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
1984 CloseHandle (token
);
1990 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
1991 return ((rand () << 15) | rand ());
2000 /* Return the maximum length in bytes of a multibyte character
2001 sequence encoded in the current ANSI codepage. This is required to
2002 correctly walk the encoded file names one character at a time. */
2004 max_filename_mbslen (void)
2008 codepage_for_filenames (&cp_info
);
2009 return cp_info
.MaxCharSize
;
2012 /* Normalize filename by converting in-place all of its path
2013 separators to the separator specified by PATH_SEP. */
2016 normalize_filename (register char *fp
, char path_sep
)
2020 /* Always lower-case drive letters a-z, even if the filesystem
2021 preserves case in filenames.
2022 This is so filenames can be compared by string comparison
2023 functions that are case-sensitive. Even case-preserving filesystems
2024 do not distinguish case in drive letters. */
2027 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2035 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2041 /* Destructively turn backslashes into slashes. */
2043 dostounix_filename (register char *p
)
2045 normalize_filename (p
, '/');
2048 /* Destructively turn slashes into backslashes. */
2050 unixtodos_filename (register char *p
)
2052 normalize_filename (p
, '\\');
2055 /* Remove all CR's that are followed by a LF.
2056 (From msdos.c...probably should figure out a way to share it,
2057 although this code isn't going to ever change.) */
2059 crlf_to_lf (register int n
, register unsigned char *buf
)
2061 unsigned char *np
= buf
;
2062 unsigned char *startp
= buf
;
2063 unsigned char *endp
= buf
+ n
;
2067 while (buf
< endp
- 1)
2071 if (*(++buf
) != 0x0a)
2082 /* Parse the root part of file name, if present. Return length and
2083 optionally store pointer to char after root. */
2085 parse_root (const char * name
, const char ** pPath
)
2087 const char * start
= name
;
2092 /* find the root name of the volume if given */
2093 if (isalpha (name
[0]) && name
[1] == ':')
2095 /* skip past drive specifier */
2097 if (IS_DIRECTORY_SEP (name
[0]))
2100 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2107 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2112 if (IS_DIRECTORY_SEP (name
[0]))
2119 return name
- start
;
2122 /* Get long base name for name; name is assumed to be absolute. */
2124 get_long_basename (char * name
, char * buf
, int size
)
2126 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2127 char fname_utf8
[MAX_UTF8_PATH
];
2131 /* Must be valid filename, no wild cards or other invalid characters. */
2132 if (strpbrk (name
, "*?|<>\""))
2135 if (w32_unicode_filenames
)
2137 wchar_t fname_utf16
[MAX_PATH
];
2138 WIN32_FIND_DATAW find_data_wide
;
2140 filename_to_utf16 (name
, fname_utf16
);
2141 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2142 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2143 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2147 char fname_ansi
[MAX_PATH
];
2148 WIN32_FIND_DATAA find_data_ansi
;
2150 filename_to_ansi (name
, fname_ansi
);
2151 /* If the ANSI name includes ? characters, it is not encodable
2152 in the ANSI codepage. In that case, we deliver the question
2153 marks to the caller; calling FindFirstFileA in this case
2154 could return some unrelated file name in the same
2156 if (_mbspbrk (fname_ansi
, "?"))
2157 cstatus
= filename_from_ansi (fname_ansi
, fname_utf8
);
2160 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2161 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2162 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2166 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2167 memcpy (buf
, fname_utf8
, len
+ 1);
2171 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2172 FindClose (dir_handle
);
2177 /* Get long name for file, if possible (assumed to be absolute). */
2179 w32_get_long_filename (char * name
, char * buf
, int size
)
2184 char full
[ MAX_UTF8_PATH
];
2187 len
= strlen (name
);
2188 if (len
>= MAX_UTF8_PATH
)
2191 /* Use local copy for destructive modification. */
2192 memcpy (full
, name
, len
+1);
2193 unixtodos_filename (full
);
2195 /* Copy root part verbatim. */
2196 len
= parse_root (full
, (const char **)&p
);
2197 memcpy (o
, full
, len
);
2202 while (p
!= NULL
&& *p
)
2205 p
= strchr (q
, '\\');
2207 len
= get_long_basename (full
, o
, size
);
2230 w32_get_short_filename (char * name
, char * buf
, int size
)
2232 if (w32_unicode_filenames
)
2234 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2235 unsigned int retval
;
2237 filename_to_utf16 (name
, name_utf16
);
2238 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2239 if (retval
&& retval
< size
)
2240 filename_from_utf16 (short_name
, buf
);
2245 char name_ansi
[MAX_PATH
];
2247 filename_to_ansi (name
, name_ansi
);
2248 return GetShortPathNameA (name_ansi
, buf
, size
);
2252 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2253 MS-Windows ANSI codepage. If FILENAME includes characters not
2254 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2255 if it exists. This is needed because the w32 build wants to
2256 support file names outside of the system locale, but image
2257 libraries typically don't support wide (a.k.a. "Unicode") APIs
2258 required for that. */
2261 ansi_encode_filename (Lisp_Object filename
)
2263 Lisp_Object encoded_filename
;
2264 char fname
[MAX_PATH
];
2266 filename_to_ansi (SSDATA (filename
), fname
);
2267 if (_mbspbrk (fname
, "?"))
2269 char shortname
[MAX_PATH
];
2271 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2273 dostounix_filename (shortname
);
2274 encoded_filename
= build_string (shortname
);
2278 encoded_filename
= build_unibyte_string (fname
);
2279 return encoded_filename
;
2283 is_unc_volume (const char *filename
)
2285 const char *ptr
= filename
;
2287 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2290 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2296 /* Emulate the Posix unsetenv. */
2298 unsetenv (const char *name
)
2304 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2309 name_len
= strlen (name
);
2310 /* MS docs says an environment variable cannot be longer than 32K. */
2311 if (name_len
> 32767)
2316 /* It is safe to use 'alloca' with 32K size, since the stack is at
2317 least 2MB, and we set it to 8MB in the link command line. */
2318 var
= alloca (name_len
+ 2);
2319 strncpy (var
, name
, name_len
);
2320 var
[name_len
++] = '=';
2321 var
[name_len
] = '\0';
2322 return _putenv (var
);
2325 /* MS _putenv doesn't support removing a variable when the argument
2326 does not include the '=' character, so we fix that here. */
2328 sys_putenv (char *str
)
2330 const char *const name_end
= strchr (str
, '=');
2332 if (name_end
== NULL
)
2334 /* Remove the variable from the environment. */
2335 return unsetenv (str
);
2338 return _putenv (str
);
2341 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2344 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2347 HKEY hrootkey
= NULL
;
2350 /* Check both the current user and the local machine to see if
2351 we have any resources. */
2353 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2357 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2358 && (lpvalue
= xmalloc (cbData
)) != NULL
2359 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2361 RegCloseKey (hrootkey
);
2367 RegCloseKey (hrootkey
);
2370 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2374 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2375 && (lpvalue
= xmalloc (cbData
)) != NULL
2376 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2378 RegCloseKey (hrootkey
);
2384 RegCloseKey (hrootkey
);
2390 /* The argv[] array holds ANSI-encoded strings, and so this function
2391 works with ANS_encoded strings. */
2393 init_environment (char ** argv
)
2395 static const char * const tempdirs
[] = {
2396 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2401 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2403 /* Implementation note: This function explicitly works with ANSI
2404 file names, not with UTF-8 encoded file names. This is because
2405 this function pushes variables into the Emacs's environment, and
2406 the environment variables are always assumed to be in the
2407 locale-specific encoding. Do NOT call any functions that accept
2408 UTF-8 file names from this function! */
2410 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2411 temporary files and assume "/tmp" if $TMPDIR is unset, which
2412 will break on DOS/Windows. Refuse to work if we cannot find
2413 a directory, not even "c:/", usable for that purpose. */
2414 for (i
= 0; i
< imax
; i
++)
2416 const char *tmp
= tempdirs
[i
];
2419 tmp
= getenv (tmp
+ 1);
2420 /* Note that `access' can lie to us if the directory resides on a
2421 read-only filesystem, like CD-ROM or a write-protected floppy.
2422 The only way to be really sure is to actually create a file and
2423 see if it succeeds. But I think that's too much to ask. */
2425 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2426 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2428 char * var
= alloca (strlen (tmp
) + 8);
2429 sprintf (var
, "TMPDIR=%s", tmp
);
2430 _putenv (strdup (var
));
2437 Fcons (build_string ("no usable temporary directories found!!"),
2439 "While setting TMPDIR: ");
2441 /* Check for environment variables and use registry settings if they
2442 don't exist. Fallback on default values where applicable. */
2447 char locale_name
[32];
2448 char default_home
[MAX_PATH
];
2451 static const struct env_entry
2457 /* If the default value is NULL, we will use the value from the
2458 outside environment or the Registry, but will not push the
2459 variable into the Emacs environment if it is defined neither
2460 in the Registry nor in the outside environment. */
2462 {"PRELOAD_WINSOCK", NULL
},
2463 {"emacs_dir", "C:/emacs"},
2464 {"EMACSLOADPATH", NULL
},
2465 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2466 {"EMACSDATA", NULL
},
2467 {"EMACSPATH", NULL
},
2474 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2476 /* We need to copy dflt_envvars[] and work on the copy because we
2477 don't want the dumped Emacs to inherit the values of
2478 environment variables we saw during dumping (which could be on
2479 a different system). The defaults above must be left intact. */
2480 struct env_entry env_vars
[N_ENV_VARS
];
2482 for (i
= 0; i
< N_ENV_VARS
; i
++)
2483 env_vars
[i
] = dflt_envvars
[i
];
2485 /* For backwards compatibility, check if a .emacs file exists in C:/
2486 If not, then we can try to default to the appdata directory under the
2487 user's profile, which is more likely to be writable. */
2488 if (sys_access ("C:/.emacs", F_OK
) != 0)
2490 HRESULT profile_result
;
2491 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2492 of Windows 95 and NT4 that have not been updated to include
2494 ShGetFolderPath_fn get_folder_path
;
2495 get_folder_path
= (ShGetFolderPath_fn
)
2496 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2498 if (get_folder_path
!= NULL
)
2500 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2503 /* If we can't get the appdata dir, revert to old behavior. */
2504 if (profile_result
== S_OK
)
2506 env_vars
[0].def_value
= default_home
;
2512 /* Get default locale info and use it for LANG. */
2513 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2514 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2515 locale_name
, sizeof (locale_name
)))
2517 for (i
= 0; i
< N_ENV_VARS
; i
++)
2519 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2521 env_vars
[i
].def_value
= locale_name
;
2527 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2529 /* Treat emacs_dir specially: set it unconditionally based on our
2533 char modname
[MAX_PATH
];
2535 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2537 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2541 if ((p
= _mbsrchr (modname
, '\\'))
2542 /* From bin means installed Emacs, from src means uninstalled. */
2543 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2545 char buf
[SET_ENV_BUF_SIZE
];
2546 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2549 for (p
= modname
; *p
; p
= CharNext (p
))
2550 if (*p
== '\\') *p
= '/';
2552 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2553 _putenv (strdup (buf
));
2554 /* If we are running from the Posix-like build tree, define
2555 SHELL to point to our own cmdproxy. The loop below will
2556 then disregard PATH_EXEC and the default value. */
2557 if (within_build_tree
)
2559 _snprintf (buf
, sizeof (buf
) - 1,
2560 "SHELL=%s/nt/cmdproxy.exe", modname
);
2561 _putenv (strdup (buf
));
2566 for (i
= 0; i
< N_ENV_VARS
; i
++)
2568 if (!getenv (env_vars
[i
].name
))
2571 char bufc
[SET_ENV_BUF_SIZE
];
2573 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2574 /* Also ignore empty environment variables. */
2579 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2581 /* Look for cmdproxy.exe in every directory in
2582 PATH_EXEC. FIXME: This does not find cmdproxy
2583 in nt/ when we run uninstalled. */
2584 char fname
[MAX_PATH
];
2585 const char *pstart
= PATH_EXEC
, *pend
;
2588 pend
= _mbschr (pstart
, ';');
2590 pend
= pstart
+ strlen (pstart
);
2591 /* Be defensive against series of ;;; characters. */
2594 strncpy (fname
, pstart
, pend
- pstart
);
2595 fname
[pend
- pstart
] = '/';
2596 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2597 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2599 if (sys_access (bufc
, F_OK
) == 0)
2612 /* If not found in any directory, use the
2613 default as the last resort. */
2614 lpval
= env_vars
[i
].def_value
;
2615 dwType
= REG_EXPAND_SZ
;
2621 lpval
= env_vars
[i
].def_value
;
2622 dwType
= REG_EXPAND_SZ
;
2624 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2625 Vdelayed_warnings_list
2626 = Fcons (listn (CONSTYPE_HEAP
, 2,
2627 intern ("initialization"),
2628 build_string ("Setting HOME to C:\\ by default is deprecated")),
2629 Vdelayed_warnings_list
);
2634 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2636 if (dwType
== REG_EXPAND_SZ
)
2637 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2638 else if (dwType
== REG_SZ
)
2639 strcpy (buf1
, lpval
);
2640 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2642 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2644 _putenv (strdup (buf2
));
2654 /* Rebuild system configuration to reflect invoking system. */
2655 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2657 /* Another special case: on NT, the PATH variable is actually named
2658 "Path" although cmd.exe (perhaps NT itself) arranges for
2659 environment variable lookup and setting to be case insensitive.
2660 However, Emacs assumes a fully case sensitive environment, so we
2661 need to change "Path" to "PATH" to match the expectations of
2662 various elisp packages. We do this by the sneaky method of
2663 modifying the string in the C runtime environ entry.
2665 The same applies to COMSPEC. */
2669 for (envp
= environ
; *envp
; envp
++)
2670 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2671 memcpy (*envp
, "PATH=", 5);
2672 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2673 memcpy (*envp
, "COMSPEC=", 8);
2676 /* Remember the initial working directory for getcwd. */
2677 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2678 Does it matter anywhere in Emacs? */
2679 if (w32_unicode_filenames
)
2681 wchar_t wstartup_dir
[MAX_PATH
];
2683 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2685 filename_from_utf16 (wstartup_dir
, startup_dir
);
2689 char astartup_dir
[MAX_PATH
];
2691 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2693 filename_from_ansi (astartup_dir
, startup_dir
);
2697 static char modname
[MAX_PATH
];
2699 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2704 /* Determine if there is a middle mouse button, to allow parse_button
2705 to decide whether right mouse events should be mouse-2 or
2707 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2712 /* Called from expand-file-name when default-directory is not a string. */
2715 emacs_root_dir (void)
2717 static char root_dir
[MAX_UTF8_PATH
];
2720 p
= getenv ("emacs_dir");
2723 filename_from_ansi (p
, root_dir
);
2724 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2725 dostounix_filename (root_dir
);
2729 #include <sys/timeb.h>
2731 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2733 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2738 tv
->tv_sec
= tb
.time
;
2739 tv
->tv_usec
= tb
.millitm
* 1000L;
2740 /* Implementation note: _ftime sometimes doesn't update the dstflag
2741 according to the new timezone when the system timezone is
2742 changed. We could fix that by using GetSystemTime and
2743 GetTimeZoneInformation, but that doesn't seem necessary, since
2744 Emacs always calls gettimeofday with the 2nd argument NULL (see
2745 current_emacs_time). */
2748 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2749 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2754 /* Emulate fdutimens. */
2756 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2757 TIMESPEC[0] and TIMESPEC[1], respectively.
2758 FD must be either negative -- in which case it is ignored --
2759 or a file descriptor that is open on FILE.
2760 If FD is nonnegative, then FILE can be NULL, which means
2761 use just futimes instead of utimes.
2762 If TIMESPEC is null, FAIL.
2763 Return 0 on success, -1 (setting errno) on failure. */
2766 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2773 if (fd
< 0 && !file
)
2778 /* _futime's prototype defines 2nd arg as having the type 'struct
2779 _utimbuf', while utime needs to accept 'struct utimbuf' for
2780 compatibility with Posix. So we need to use 2 different (but
2781 equivalent) types to avoid compiler warnings, sigh. */
2784 struct _utimbuf _ut
;
2786 _ut
.actime
= timespec
[0].tv_sec
;
2787 _ut
.modtime
= timespec
[1].tv_sec
;
2788 return _futime (fd
, &_ut
);
2794 ut
.actime
= timespec
[0].tv_sec
;
2795 ut
.modtime
= timespec
[1].tv_sec
;
2796 /* Call 'utime', which is implemented below, not the MS library
2797 function, which fails on directories. */
2798 return utime (file
, &ut
);
2803 /* ------------------------------------------------------------------------- */
2804 /* IO support and wrapper functions for the Windows API. */
2805 /* ------------------------------------------------------------------------- */
2807 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2808 on network directories, so we handle that case here.
2809 (Ulrich Leodolter, 1/11/95). */
2811 sys_ctime (const time_t *t
)
2813 char *str
= (char *) ctime (t
);
2814 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2817 /* Emulate sleep...we could have done this with a define, but that
2818 would necessitate including windows.h in the files that used it.
2819 This is much easier. */
2821 sys_sleep (int seconds
)
2823 Sleep (seconds
* 1000);
2826 /* Internal MSVC functions for low-level descriptor munging */
2827 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2828 extern int __cdecl
_free_osfhnd (int fd
);
2830 /* parallel array of private info on file handles */
2831 filedesc fd_info
[ MAXDESC
];
2833 typedef struct volume_info_data
{
2834 struct volume_info_data
* next
;
2836 /* time when info was obtained */
2839 /* actual volume info */
2848 /* Global referenced by various functions. */
2849 static volume_info_data volume_info
;
2851 /* Vector to indicate which drives are local and fixed (for which cached
2852 data never expires). */
2853 static BOOL fixed_drives
[26];
2855 /* Consider cached volume information to be stale if older than 10s,
2856 at least for non-local drives. Info for fixed drives is never stale. */
2857 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2858 #define VOLINFO_STILL_VALID( root_dir, info ) \
2859 ( ( isalpha (root_dir[0]) && \
2860 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2861 || GetTickCount () - info->timestamp < 10000 )
2863 /* Cache support functions. */
2865 /* Simple linked list with linear search is sufficient. */
2866 static volume_info_data
*volume_cache
= NULL
;
2868 static volume_info_data
*
2869 lookup_volume_info (char * root_dir
)
2871 volume_info_data
* info
;
2873 for (info
= volume_cache
; info
; info
= info
->next
)
2874 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2880 add_volume_info (char * root_dir
, volume_info_data
* info
)
2882 info
->root_dir
= xstrdup (root_dir
);
2883 unixtodos_filename (info
->root_dir
);
2884 info
->next
= volume_cache
;
2885 volume_cache
= info
;
2889 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2890 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2891 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2892 static volume_info_data
*
2893 GetCachedVolumeInformation (char * root_dir
)
2895 volume_info_data
* info
;
2896 char default_root
[ MAX_UTF8_PATH
];
2897 char name
[MAX_PATH
+1];
2898 char type
[MAX_PATH
+1];
2900 /* NULL for root_dir means use root from current directory. */
2901 if (root_dir
== NULL
)
2903 if (w32_unicode_filenames
)
2905 wchar_t curdirw
[MAX_PATH
];
2907 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
2909 filename_from_utf16 (curdirw
, default_root
);
2913 char curdira
[MAX_PATH
];
2915 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
2917 filename_from_ansi (curdira
, default_root
);
2919 parse_root (default_root
, (const char **)&root_dir
);
2921 root_dir
= default_root
;
2924 /* Local fixed drives can be cached permanently. Removable drives
2925 cannot be cached permanently, since the volume name and serial
2926 number (if nothing else) can change. Remote drives should be
2927 treated as if they are removable, since there is no sure way to
2928 tell whether they are or not. Also, the UNC association of drive
2929 letters mapped to remote volumes can be changed at any time (even
2930 by other processes) without notice.
2932 As a compromise, so we can benefit from caching info for remote
2933 volumes, we use a simple expiry mechanism to invalidate cache
2934 entries that are more than ten seconds old. */
2937 /* No point doing this, because WNetGetConnection is even slower than
2938 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2939 GetDriveType is about the only call of this type which does not
2940 involve network access, and so is extremely quick). */
2942 /* Map drive letter to UNC if remote. */
2943 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2945 char remote_name
[ 256 ];
2946 char drive
[3] = { root_dir
[0], ':' };
2948 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2950 /* do something */ ;
2954 info
= lookup_volume_info (root_dir
);
2956 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2962 /* Info is not cached, or is stale. */
2963 if (w32_unicode_filenames
)
2965 wchar_t root_w
[MAX_PATH
];
2966 wchar_t name_w
[MAX_PATH
+1];
2967 wchar_t type_w
[MAX_PATH
+1];
2969 filename_to_utf16 (root_dir
, root_w
);
2970 if (!GetVolumeInformationW (root_w
,
2971 name_w
, sizeof (name_w
),
2975 type_w
, sizeof (type_w
)))
2977 /* Hmm... not really 100% correct, as these 2 are not file
2979 filename_from_utf16 (name_w
, name
);
2980 filename_from_utf16 (type_w
, type
);
2984 char root_a
[MAX_PATH
];
2985 char name_a
[MAX_PATH
+1];
2986 char type_a
[MAX_PATH
+1];
2988 filename_to_ansi (root_dir
, root_a
);
2989 if (!GetVolumeInformationA (root_a
,
2990 name_a
, sizeof (name_a
),
2994 type_a
, sizeof (type_a
)))
2996 filename_from_ansi (name_a
, name
);
2997 filename_from_ansi (type_a
, type
);
3000 /* Cache the volume information for future use, overwriting existing
3001 entry if present. */
3004 info
= xmalloc (sizeof (volume_info_data
));
3005 add_volume_info (root_dir
, info
);
3013 info
->name
= xstrdup (name
);
3014 unixtodos_filename (info
->name
);
3015 info
->serialnum
= serialnum
;
3016 info
->maxcomp
= maxcomp
;
3017 info
->flags
= flags
;
3018 info
->type
= xstrdup (type
);
3019 info
->timestamp
= GetTickCount ();
3025 /* Get information on the volume where NAME is held; set path pointer to
3026 start of pathname in NAME (past UNC header\volume header if present),
3027 if pPath is non-NULL.
3029 Note: if NAME includes symlinks, the information is for the volume
3030 of the symlink, not of its target. That's because, even though
3031 GetVolumeInformation returns information about the symlink target
3032 of its argument, we only pass the root directory to
3033 GetVolumeInformation, not the full NAME. */
3035 get_volume_info (const char * name
, const char ** pPath
)
3037 char temp
[MAX_UTF8_PATH
];
3038 char *rootname
= NULL
; /* default to current volume */
3039 volume_info_data
* info
;
3040 int root_len
= parse_root (name
, pPath
);
3045 /* Copy the root name of the volume, if given. */
3048 strncpy (temp
, name
, root_len
);
3049 temp
[root_len
] = '\0';
3050 unixtodos_filename (temp
);
3054 info
= GetCachedVolumeInformation (rootname
);
3057 /* Set global referenced by other functions. */
3058 volume_info
= *info
;
3064 /* Determine if volume is FAT format (ie. only supports short 8.3
3065 names); also set path pointer to start of pathname in name, if
3066 pPath is non-NULL. */
3068 is_fat_volume (const char * name
, const char ** pPath
)
3070 if (get_volume_info (name
, pPath
))
3071 return (volume_info
.maxcomp
== 12);
3075 /* Convert all slashes in a filename to backslashes, and map filename
3076 to a valid 8.3 name if necessary. The result is a pointer to a
3077 static buffer, so CAVEAT EMPTOR! */
3079 map_w32_filename (const char * name
, const char ** pPath
)
3081 static char shortname
[MAX_UTF8_PATH
];
3082 char * str
= shortname
;
3085 const char * save_name
= name
;
3087 if (strlen (name
) >= sizeof (shortname
))
3089 /* Return a filename which will cause callers to fail. */
3090 strcpy (shortname
, "?");
3094 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3096 register int left
= 8; /* maximum number of chars in part */
3097 register int extn
= 0; /* extension added? */
3098 register int dots
= 2; /* maximum number of dots allowed */
3101 *str
++ = *name
++; /* skip past UNC header */
3103 while ((c
= *name
++))
3110 *str
++ = (c
== ':' ? ':' : '\\');
3111 extn
= 0; /* reset extension flags */
3112 dots
= 2; /* max 2 dots */
3113 left
= 8; /* max length 8 for main part */
3118 /* Convert path components of the form .xxx to _xxx,
3119 but leave . and .. as they are. This allows .emacs
3120 to be read as _emacs, for example. */
3124 IS_DIRECTORY_SEP (*name
))
3139 extn
= 1; /* we've got an extension */
3140 left
= 3; /* 3 chars in extension */
3144 /* any embedded dots after the first are converted to _ */
3149 case '#': /* don't lose these, they're important */
3151 str
[-1] = c
; /* replace last character of part */
3154 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3156 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3158 dots
= 0; /* started a path component */
3167 strcpy (shortname
, name
);
3168 unixtodos_filename (shortname
);
3172 *pPath
= shortname
+ (path
- save_name
);
3178 is_exec (const char * name
)
3180 char * p
= strrchr (name
, '.');
3183 && (xstrcasecmp (p
, ".exe") == 0 ||
3184 xstrcasecmp (p
, ".com") == 0 ||
3185 xstrcasecmp (p
, ".bat") == 0 ||
3186 xstrcasecmp (p
, ".cmd") == 0));
3189 /* Emulate the Unix directory procedures opendir, closedir, and
3190 readdir. We rename them to sys_* names because some versions of
3191 MinGW startup code call opendir and readdir to glob wildcards, and
3192 the code that calls them doesn't grok UTF-8 encoded file names we
3193 produce in dirent->d_name[]. */
3195 struct dirent dir_static
; /* simulated directory contents */
3196 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3197 static int dir_is_fat
;
3198 static char dir_pathname
[MAX_UTF8_PATH
];
3199 static WIN32_FIND_DATAW dir_find_data_w
;
3200 static WIN32_FIND_DATAA dir_find_data_a
;
3201 #define DIR_FIND_DATA_W 1
3202 #define DIR_FIND_DATA_A 2
3203 static int last_dir_find_data
= -1;
3205 /* Support shares on a network resource as subdirectories of a read-only
3207 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3208 static HANDLE
open_unc_volume (const char *);
3209 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3210 static void close_unc_volume (HANDLE
);
3213 sys_opendir (const char *filename
)
3217 /* Opening is done by FindFirstFile. However, a read is inherent to
3218 this operation, so we defer the open until read time. */
3220 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3222 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3225 /* Note: We don't support traversal of UNC volumes via symlinks.
3226 Doing so would mean punishing 99.99% of use cases by resolving
3227 all the possible symlinks in FILENAME, recursively. */
3228 if (is_unc_volume (filename
))
3230 wnet_enum_handle
= open_unc_volume (filename
);
3231 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3235 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3242 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3243 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3244 /* Note: We don't support symlinks to file names on FAT volumes.
3245 Doing so would mean punishing 99.99% of use cases by resolving
3246 all the possible symlinks in FILENAME, recursively. */
3247 dir_is_fat
= is_fat_volume (filename
, NULL
);
3253 sys_closedir (DIR *dirp
)
3255 /* If we have a find-handle open, close it. */
3256 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3258 FindClose (dir_find_handle
);
3259 dir_find_handle
= INVALID_HANDLE_VALUE
;
3261 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3263 close_unc_volume (wnet_enum_handle
);
3264 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3266 xfree ((char *) dirp
);
3270 sys_readdir (DIR *dirp
)
3272 int downcase
= !NILP (Vw32_downcase_file_names
);
3274 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3276 if (!read_unc_volume (wnet_enum_handle
,
3277 dir_find_data_w
.cFileName
,
3278 dir_find_data_a
.cFileName
,
3282 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3283 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3285 char filename
[MAX_UTF8_PATH
+ 2];
3288 strcpy (filename
, dir_pathname
);
3289 ln
= strlen (filename
) - 1;
3290 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3291 strcat (filename
, "\\");
3292 strcat (filename
, "*");
3294 /* Note: No need to resolve symlinks in FILENAME, because
3295 FindFirst opens the directory that is the target of a
3297 if (w32_unicode_filenames
)
3299 wchar_t fnw
[MAX_PATH
];
3301 filename_to_utf16 (filename
, fnw
);
3302 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3308 filename_to_ansi (filename
, fna
);
3309 /* If FILENAME is not representable by the current ANSI
3310 codepage, we don't want FindFirstFileA to interpret the
3311 '?' characters as a wildcard. */
3312 if (_mbspbrk (fna
, "?"))
3313 dir_find_handle
= INVALID_HANDLE_VALUE
;
3315 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3318 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3321 else if (w32_unicode_filenames
)
3323 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3328 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3332 /* Emacs never uses this value, so don't bother making it match
3333 value returned by stat(). */
3334 dir_static
.d_ino
= 1;
3336 if (w32_unicode_filenames
)
3338 if (downcase
|| dir_is_fat
)
3340 wchar_t tem
[MAX_PATH
];
3342 wcscpy (tem
, dir_find_data_w
.cFileName
);
3344 filename_from_utf16 (tem
, dir_static
.d_name
);
3347 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3348 last_dir_find_data
= DIR_FIND_DATA_W
;
3354 /* If the file name in cFileName[] includes `?' characters, it
3355 means the original file name used characters that cannot be
3356 represented by the current ANSI codepage. To avoid total
3357 lossage, retrieve the short 8+3 alias of the long file
3359 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3361 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3362 /* 8+3 aliases are returned in all caps, which could break
3363 various alists that look at filenames' extensions. */
3366 else if (downcase
|| dir_is_fat
)
3367 strcpy (tem
, dir_find_data_a
.cFileName
);
3369 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3370 if (downcase
|| dir_is_fat
)
3373 filename_from_ansi (tem
, dir_static
.d_name
);
3375 last_dir_find_data
= DIR_FIND_DATA_A
;
3378 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3379 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3380 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3386 open_unc_volume (const char *path
)
3388 const char *fn
= map_w32_filename (path
, NULL
);
3392 if (w32_unicode_filenames
)
3395 wchar_t fnw
[MAX_PATH
];
3397 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3398 nrw
.dwType
= RESOURCETYPE_DISK
;
3399 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3400 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3401 nrw
.lpLocalName
= NULL
;
3402 filename_to_utf16 (fn
, fnw
);
3403 nrw
.lpRemoteName
= fnw
;
3404 nrw
.lpComment
= NULL
;
3405 nrw
.lpProvider
= NULL
;
3407 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3408 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3415 nra
.dwScope
= RESOURCE_GLOBALNET
;
3416 nra
.dwType
= RESOURCETYPE_DISK
;
3417 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3418 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3419 nra
.lpLocalName
= NULL
;
3420 filename_to_ansi (fn
, fna
);
3421 nra
.lpRemoteName
= fna
;
3422 nra
.lpComment
= NULL
;
3423 nra
.lpProvider
= NULL
;
3425 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3426 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3428 if (result
== NO_ERROR
)
3431 return INVALID_HANDLE_VALUE
;
3435 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3440 DWORD bufsize
= 512;
3444 if (w32_unicode_filenames
)
3449 buffer
= alloca (bufsize
);
3450 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3451 if (result
!= NO_ERROR
)
3453 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3454 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3456 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3458 wcsncpy (fname_w
, ptrw
, size
);
3463 int dbcs_p
= max_filename_mbslen () > 1;
3466 buffer
= alloca (bufsize
);
3467 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3468 if (result
!= NO_ERROR
)
3470 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3473 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3476 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3477 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3480 strncpy (fname_a
, ptra
, size
);
3488 close_unc_volume (HANDLE henum
)
3490 if (henum
!= INVALID_HANDLE_VALUE
)
3491 WNetCloseEnum (henum
);
3495 unc_volume_file_attributes (const char *path
)
3500 henum
= open_unc_volume (path
);
3501 if (henum
== INVALID_HANDLE_VALUE
)
3504 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3506 close_unc_volume (henum
);
3511 /* Ensure a network connection is authenticated. */
3513 logon_network_drive (const char *path
)
3515 char share
[MAX_UTF8_PATH
];
3522 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3523 drvtype
= DRIVE_REMOTE
;
3524 else if (path
[0] == '\0' || path
[1] != ':')
3525 drvtype
= GetDriveType (NULL
);
3532 drvtype
= GetDriveType (drive
);
3535 /* Only logon to networked drives. */
3536 if (drvtype
!= DRIVE_REMOTE
)
3540 strncpy (share
, path
, MAX_UTF8_PATH
);
3541 /* Truncate to just server and share name. */
3542 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3544 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3551 if (w32_unicode_filenames
)
3553 NETRESOURCEW resourcew
;
3554 wchar_t share_w
[MAX_PATH
];
3556 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3557 resourcew
.dwType
= RESOURCETYPE_DISK
;
3558 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3559 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3560 resourcew
.lpLocalName
= NULL
;
3561 filename_to_utf16 (share
, share_w
);
3562 resourcew
.lpRemoteName
= share_w
;
3563 resourcew
.lpProvider
= NULL
;
3565 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3569 NETRESOURCEA resourcea
;
3570 char share_a
[MAX_PATH
];
3572 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3573 resourcea
.dwType
= RESOURCETYPE_DISK
;
3574 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3575 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3576 resourcea
.lpLocalName
= NULL
;
3577 filename_to_ansi (share
, share_a
);
3578 resourcea
.lpRemoteName
= share_a
;
3579 resourcea
.lpProvider
= NULL
;
3581 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3587 case ERROR_ALREADY_ASSIGNED
:
3589 case ERROR_ACCESS_DENIED
:
3590 case ERROR_LOGON_FAILURE
:
3596 case ERROR_BAD_NET_NAME
:
3597 case ERROR_NO_NET_OR_BAD_PATH
:
3598 case ERROR_NO_NETWORK
:
3599 case ERROR_CANCELLED
:
3606 /* Emulate faccessat(2). */
3608 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3612 if (dirfd
!= AT_FDCWD
3613 && !(IS_DIRECTORY_SEP (path
[0])
3614 || IS_DEVICE_SEP (path
[1])))
3620 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3621 newer versions blow up when passed D_OK. */
3622 path
= map_w32_filename (path
, NULL
);
3623 /* If the last element of PATH is a symlink, we need to resolve it
3624 to get the attributes of its target file. Note: any symlinks in
3625 PATH elements other than the last one are transparently resolved
3626 by GetFileAttributes below. */
3627 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3628 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3629 path
= chase_symlinks (path
);
3631 if (w32_unicode_filenames
)
3633 wchar_t path_w
[MAX_PATH
];
3635 filename_to_utf16 (path
, path_w
);
3636 attributes
= GetFileAttributesW (path_w
);
3640 char path_a
[MAX_PATH
];
3642 filename_to_ansi (path
, path_a
);
3643 attributes
= GetFileAttributesA (path_a
);
3646 if (attributes
== -1)
3648 DWORD w32err
= GetLastError ();
3652 case ERROR_INVALID_NAME
:
3653 case ERROR_BAD_PATHNAME
:
3654 if (is_unc_volume (path
))
3656 attributes
= unc_volume_file_attributes (path
);
3657 if (attributes
== -1)
3665 case ERROR_FILE_NOT_FOUND
:
3666 case ERROR_BAD_NETPATH
:
3675 if ((mode
& X_OK
) != 0
3676 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3681 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3686 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3694 /* A version of 'access' to be used locally with file names in
3695 locale-specific encoding. Does not resolve symlinks and does not
3696 support file names on FAT12 and FAT16 volumes, but that's OK, since
3697 we only invoke this function for files inside the Emacs source or
3698 installation tree, on directories (so any symlinks should have the
3699 directory bit set), and on short file names such as "C:/.emacs". */
3701 sys_access (const char *fname
, int mode
)
3703 char fname_copy
[MAX_PATH
], *p
;
3706 strcpy (fname_copy
, fname
);
3707 /* Do the equivalent of unixtodos_filename. */
3708 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3712 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3714 DWORD w32err
= GetLastError ();
3718 case ERROR_INVALID_NAME
:
3719 case ERROR_BAD_PATHNAME
:
3720 case ERROR_FILE_NOT_FOUND
:
3721 case ERROR_BAD_NETPATH
:
3730 if ((mode
& X_OK
) != 0
3731 && !(is_exec (fname_copy
)
3732 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3737 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3742 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3750 /* Shadow some MSVC runtime functions to map requests for long filenames
3751 to reasonable short names if necessary. This was originally added to
3752 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3756 sys_chdir (const char * path
)
3758 path
= map_w32_filename (path
, NULL
);
3759 if (w32_unicode_filenames
)
3761 wchar_t newdir_w
[MAX_PATH
];
3763 if (filename_to_utf16 (path
, newdir_w
) == 0)
3764 return _wchdir (newdir_w
);
3769 char newdir_a
[MAX_PATH
];
3771 if (filename_to_ansi (path
, newdir_a
) == 0)
3772 return _chdir (newdir_a
);
3778 sys_chmod (const char * path
, int mode
)
3780 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3781 if (w32_unicode_filenames
)
3783 wchar_t path_w
[MAX_PATH
];
3785 filename_to_utf16 (path
, path_w
);
3786 return _wchmod (path_w
, mode
);
3790 char path_a
[MAX_PATH
];
3792 filename_to_ansi (path
, path_a
);
3793 return _chmod (path_a
, mode
);
3798 sys_creat (const char * path
, int mode
)
3800 path
= map_w32_filename (path
, NULL
);
3801 if (w32_unicode_filenames
)
3803 wchar_t path_w
[MAX_PATH
];
3805 filename_to_utf16 (path
, path_w
);
3806 return _wcreat (path_w
, mode
);
3810 char path_a
[MAX_PATH
];
3812 filename_to_ansi (path
, path_a
);
3813 return _creat (path_a
, mode
);
3818 sys_fopen (const char * path
, const char * mode
)
3822 const char * mode_save
= mode
;
3824 /* Force all file handles to be non-inheritable. This is necessary to
3825 ensure child processes don't unwittingly inherit handles that might
3826 prevent future file access. */
3830 else if (mode
[0] == 'w' || mode
[0] == 'a')
3831 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3835 /* Only do simplistic option parsing. */
3839 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3842 else if (mode
[0] == 'b')
3847 else if (mode
[0] == 't')
3854 path
= map_w32_filename (path
, NULL
);
3855 if (w32_unicode_filenames
)
3857 wchar_t path_w
[MAX_PATH
];
3859 filename_to_utf16 (path
, path_w
);
3860 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3864 char path_a
[MAX_PATH
];
3866 filename_to_ansi (path
, path_a
);
3867 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3872 return _fdopen (fd
, mode_save
);
3875 /* This only works on NTFS volumes, but is useful to have. */
3877 sys_link (const char * old
, const char * new)
3881 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3882 wchar_t oldname_w
[MAX_PATH
];
3883 char oldname_a
[MAX_PATH
];
3885 if (old
== NULL
|| new == NULL
)
3891 strcpy (oldname
, map_w32_filename (old
, NULL
));
3892 strcpy (newname
, map_w32_filename (new, NULL
));
3894 if (w32_unicode_filenames
)
3896 filename_to_utf16 (oldname
, oldname_w
);
3897 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
3898 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3902 filename_to_ansi (oldname
, oldname_a
);
3903 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
3904 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3906 if (fileh
!= INVALID_HANDLE_VALUE
)
3910 /* Confusingly, the "alternate" stream name field does not apply
3911 when restoring a hard link, and instead contains the actual
3912 stream data for the link (ie. the name of the link to create).
3913 The WIN32_STREAM_ID structure before the cStreamName field is
3914 the stream header, which is then immediately followed by the
3918 WIN32_STREAM_ID wid
;
3919 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3922 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
3923 indicates that flag is unsupported for CP_UTF8, and OTOH says
3924 it is the default anyway. */
3925 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
3926 data
.wid
.cStreamName
, MAX_PATH
);
3929 LPVOID context
= NULL
;
3932 data
.wid
.dwStreamId
= BACKUP_LINK
;
3933 data
.wid
.dwStreamAttributes
= 0;
3934 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3935 data
.wid
.Size
.HighPart
= 0;
3936 data
.wid
.dwStreamNameSize
= 0;
3938 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3939 offsetof (WIN32_STREAM_ID
, cStreamName
)
3940 + data
.wid
.Size
.LowPart
,
3941 &wbytes
, FALSE
, FALSE
, &context
)
3942 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3949 DWORD err
= GetLastError ();
3954 case ERROR_ACCESS_DENIED
:
3955 /* This is what happens when OLDNAME is a directory,
3956 since Windows doesn't support hard links to
3957 directories. Posix says to set errno to EPERM in
3959 if (w32_unicode_filenames
)
3960 attributes
= GetFileAttributesW (oldname_w
);
3962 attributes
= GetFileAttributesA (oldname_a
);
3963 if (attributes
!= -1
3964 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
3966 else if (attributes
== -1
3967 && is_unc_volume (oldname
)
3968 && unc_volume_file_attributes (oldname
) != -1)
3973 case ERROR_TOO_MANY_LINKS
:
3976 case ERROR_NOT_SAME_DEVICE
:
3986 CloseHandle (fileh
);
3995 sys_mkdir (const char * path
)
3997 path
= map_w32_filename (path
, NULL
);
3999 if (w32_unicode_filenames
)
4001 wchar_t path_w
[MAX_PATH
];
4003 filename_to_utf16 (path
, path_w
);
4004 return _wmkdir (path_w
);
4008 char path_a
[MAX_PATH
];
4010 filename_to_ansi (path
, path_a
);
4011 return _mkdir (path_a
);
4016 sys_open (const char * path
, int oflag
, int mode
)
4018 const char* mpath
= map_w32_filename (path
, NULL
);
4021 if (w32_unicode_filenames
)
4023 wchar_t mpath_w
[MAX_PATH
];
4025 filename_to_utf16 (mpath
, mpath_w
);
4026 /* If possible, try to open file without _O_CREAT, to be able to
4027 write to existing hidden and system files. Force all file
4028 handles to be non-inheritable. */
4029 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4030 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4032 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4036 char mpath_a
[MAX_PATH
];
4038 filename_to_ansi (mpath
, mpath_a
);
4039 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4040 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4042 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4048 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4051 Standard algorithm for generating a temporary file name seems to be
4052 use pid or tid with a letter on the front (in place of the 6 X's)
4053 and cycle through the letters to find a unique name. We extend
4054 that to allow any reasonable character as the first of the 6 X's,
4055 so that the number of simultaneously used temporary files will be
4059 mkostemp (char * template, int flags
)
4063 unsigned uid
= GetCurrentThreadId ();
4064 int save_errno
= errno
;
4065 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4068 if (template == NULL
)
4071 p
= template + strlen (template);
4073 /* replace up to the last 5 X's with uid in decimal */
4074 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4076 p
[0] = '0' + uid
% 10;
4080 if (i
< 0 && p
[0] == 'X')
4085 p
[0] = first_char
[i
];
4086 if ((fd
= sys_open (template,
4087 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4088 S_IRUSR
| S_IWUSR
)) >= 0
4096 while (++i
< sizeof (first_char
));
4099 /* Template is badly formed or else we can't generate a unique name. */
4104 fchmod (int fd
, mode_t mode
)
4110 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4113 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4116 bool have_temp_a
= false;
4118 /* MoveFile on Windows 95 doesn't correctly change the short file name
4119 alias in a number of circumstances (it is not easy to predict when
4120 just by looking at oldname and newname, unfortunately). In these
4121 cases, renaming through a temporary name avoids the problem.
4123 A second problem on Windows 95 is that renaming through a temp name when
4124 newname is uppercase fails (the final long name ends up in
4125 lowercase, although the short alias might be uppercase) UNLESS the
4126 long temp name is not 8.3.
4128 So, on Windows 95 we always rename through a temp name, and we make sure
4129 the temp name has a long extension to ensure correct renaming. */
4131 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4133 /* volume_info is set indirectly by map_w32_filename. */
4134 oldname_dev
= volume_info
.serialnum
;
4136 if (os_subtype
== OS_9X
)
4141 char oldname_a
[MAX_PATH
];
4143 oldname
= map_w32_filename (oldname
, NULL
);
4144 filename_to_ansi (oldname
, oldname_a
);
4145 filename_to_ansi (temp
, temp_a
);
4146 if ((o
= strrchr (oldname_a
, '\\')))
4149 o
= (char *) oldname_a
;
4151 if ((p
= strrchr (temp_a
, '\\')))
4158 /* Force temp name to require a manufactured 8.3 alias - this
4159 seems to make the second rename work properly. */
4160 sprintf (p
, "_.%s.%u", o
, i
);
4162 result
= rename (oldname_a
, temp_a
);
4164 /* This loop must surely terminate! */
4165 while (result
< 0 && errno
== EEXIST
);
4171 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4172 (at least if it is a file; don't do this for directories).
4174 Since we mustn't do this if we are just changing the case of the
4175 file name (we would end up deleting the file we are trying to
4176 rename!), we let rename detect if the destination file already
4177 exists - that way we avoid the possible pitfalls of trying to
4178 determine ourselves whether two names really refer to the same
4179 file, which is not always possible in the general case. (Consider
4180 all the permutations of shared or subst'd drives, etc.) */
4182 newname
= map_w32_filename (newname
, NULL
);
4184 /* volume_info is set indirectly by map_w32_filename. */
4185 newname_dev
= volume_info
.serialnum
;
4187 if (w32_unicode_filenames
)
4189 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4191 filename_to_utf16 (temp
, temp_w
);
4192 filename_to_utf16 (newname
, newname_w
);
4193 result
= _wrename (temp_w
, newname_w
);
4194 if (result
< 0 && force
)
4196 DWORD w32err
= GetLastError ();
4199 && newname_dev
!= oldname_dev
)
4201 /* The implementation of `rename' on Windows does not return
4202 errno = EXDEV when you are moving a directory to a
4203 different storage device (ex. logical disk). It returns
4204 EACCES instead. So here we handle such situations and
4208 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4209 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4212 else if (errno
== EEXIST
)
4214 if (_wchmod (newname_w
, 0666) != 0)
4216 if (_wunlink (newname_w
) != 0)
4218 result
= _wrename (temp_w
, newname_w
);
4220 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4221 && is_symlink (temp
))
4223 /* This is Windows prohibiting the user from creating a
4224 symlink in another place, since that requires
4232 char newname_a
[MAX_PATH
];
4235 filename_to_ansi (temp
, temp_a
);
4236 filename_to_ansi (newname
, newname_a
);
4237 result
= rename (temp_a
, newname_a
);
4238 if (result
< 0 && force
)
4240 DWORD w32err
= GetLastError ();
4243 && newname_dev
!= oldname_dev
)
4247 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4248 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4251 else if (errno
== EEXIST
)
4253 if (_chmod (newname_a
, 0666) != 0)
4255 if (_unlink (newname_a
) != 0)
4257 result
= rename (temp_a
, newname_a
);
4259 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4260 && is_symlink (temp
))
4269 sys_rename (char const *old
, char const *new)
4271 return sys_rename_replace (old
, new, TRUE
);
4275 sys_rmdir (const char * path
)
4277 path
= map_w32_filename (path
, NULL
);
4279 if (w32_unicode_filenames
)
4281 wchar_t path_w
[MAX_PATH
];
4283 filename_to_utf16 (path
, path_w
);
4284 return _wrmdir (path_w
);
4288 char path_a
[MAX_PATH
];
4290 filename_to_ansi (path
, path_a
);
4291 return _rmdir (path_a
);
4296 sys_unlink (const char * path
)
4298 path
= map_w32_filename (path
, NULL
);
4300 if (w32_unicode_filenames
)
4302 wchar_t path_w
[MAX_PATH
];
4304 filename_to_utf16 (path
, path_w
);
4305 /* On Unix, unlink works without write permission. */
4306 _wchmod (path_w
, 0666);
4307 return _wunlink (path_w
);
4311 char path_a
[MAX_PATH
];
4313 filename_to_ansi (path
, path_a
);
4314 _chmod (path_a
, 0666);
4315 return _unlink (path_a
);
4319 static FILETIME utc_base_ft
;
4320 static ULONGLONG utc_base
; /* In 100ns units */
4321 static int init
= 0;
4323 #define FILETIME_TO_U64(result, ft) \
4325 ULARGE_INTEGER uiTemp; \
4326 uiTemp.LowPart = (ft).dwLowDateTime; \
4327 uiTemp.HighPart = (ft).dwHighDateTime; \
4328 result = uiTemp.QuadPart; \
4332 initialize_utc_base (void)
4334 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4343 st
.wMilliseconds
= 0;
4345 SystemTimeToFileTime (&st
, &utc_base_ft
);
4346 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4350 convert_time (FILETIME ft
)
4356 initialize_utc_base ();
4360 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4363 FILETIME_TO_U64 (tmp
, ft
);
4364 return (time_t) ((tmp
- utc_base
) / 10000000L);
4368 convert_from_time_t (time_t time
, FILETIME
* pft
)
4374 initialize_utc_base ();
4378 /* time in 100ns units since 1-Jan-1601 */
4379 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4380 pft
->dwHighDateTime
= tmp
.HighPart
;
4381 pft
->dwLowDateTime
= tmp
.LowPart
;
4384 static PSECURITY_DESCRIPTOR
4385 get_file_security_desc_by_handle (HANDLE h
)
4387 PSECURITY_DESCRIPTOR psd
= NULL
;
4389 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4390 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4392 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4393 NULL
, NULL
, NULL
, NULL
, &psd
);
4394 if (err
!= ERROR_SUCCESS
)
4400 static PSECURITY_DESCRIPTOR
4401 get_file_security_desc_by_name (const char *fname
)
4403 PSECURITY_DESCRIPTOR psd
= NULL
;
4405 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4406 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4408 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4410 err
= GetLastError ();
4411 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4415 psd
= xmalloc (sd_len
);
4416 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4428 unsigned n_subauthorities
;
4430 /* Use the last sub-authority value of the RID, the relative
4431 portion of the SID, as user/group ID. */
4432 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4433 if (n_subauthorities
< 1)
4434 return 0; /* the "World" RID */
4435 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4438 /* Caching SID and account values for faster lokup. */
4442 struct w32_id
*next
;
4444 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4447 static struct w32_id
*w32_idlist
;
4450 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4452 struct w32_id
*tail
, *found
;
4454 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4456 if (equal_sid ((PSID
)tail
->sid
, sid
))
4465 strcpy (name
, found
->name
);
4473 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4476 struct w32_id
*new_entry
;
4478 /* We don't want to leave behind stale cache from when Emacs was
4482 sid_len
= get_length_sid (sid
);
4483 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4486 new_entry
->rid
= id
;
4487 strcpy (new_entry
->name
, name
);
4488 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4489 new_entry
->next
= w32_idlist
;
4490 w32_idlist
= new_entry
;
4499 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4503 SID_NAME_USE ignore
;
4505 DWORD name_len
= sizeof (name
);
4507 DWORD domain_len
= sizeof (domain
);
4512 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4513 else if (what
== GID
)
4514 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4518 if (!result
|| !is_valid_sid (sid
))
4520 else if (!w32_cached_id (sid
, id
, nm
))
4522 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4523 domain
, &domain_len
, &ignore
)
4524 || name_len
> UNLEN
+1)
4528 *id
= get_rid (sid
);
4530 w32_add_to_cache (sid
, *id
, name
);
4537 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4539 int dflt_usr
= 0, dflt_grp
= 0;
4548 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4550 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4553 /* Consider files to belong to current user/group, if we cannot get
4554 more accurate information. */
4557 st
->st_uid
= dflt_passwd
.pw_uid
;
4558 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4562 st
->st_gid
= dflt_passwd
.pw_gid
;
4563 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4567 /* Return non-zero if NAME is a potentially slow filesystem. */
4569 is_slow_fs (const char *name
)
4574 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4575 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4576 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4577 devtype
= GetDriveType (NULL
); /* use root of current drive */
4580 /* GetDriveType needs the root directory of the drive. */
4581 strncpy (drive_root
, name
, 2);
4582 drive_root
[2] = '\\';
4583 drive_root
[3] = '\0';
4584 devtype
= GetDriveType (drive_root
);
4586 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4589 /* If this is non-zero, the caller wants accurate information about
4590 file's owner and group, which could be expensive to get. dired.c
4591 uses this flag when needed for the job at hand. */
4592 int w32_stat_get_owner_group
;
4594 /* MSVC stat function can't cope with UNC names and has other bugs, so
4595 replace it with our own. This also allows us to calculate consistent
4596 inode values and owner/group without hacks in the main Emacs code,
4597 and support file names encoded in UTF-8. */
4600 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4602 char *name
, *save_name
, *r
;
4603 WIN32_FIND_DATAW wfd_w
;
4604 WIN32_FIND_DATAA wfd_a
;
4606 unsigned __int64 fake_inode
= 0;
4609 int rootdir
= FALSE
;
4610 PSECURITY_DESCRIPTOR psd
= NULL
;
4611 int is_a_symlink
= 0;
4612 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4613 DWORD access_rights
= 0;
4614 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4615 FILETIME ctime
, atime
, wtime
;
4616 wchar_t name_w
[MAX_PATH
];
4617 char name_a
[MAX_PATH
];
4619 if (path
== NULL
|| buf
== NULL
)
4625 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4626 /* Must be valid filename, no wild cards or other invalid
4628 if (strpbrk (name
, "*?|<>\""))
4634 /* Remove trailing directory separator, unless name is the root
4635 directory of a drive or UNC volume in which case ensure there
4636 is a trailing separator. */
4637 len
= strlen (name
);
4638 name
= strcpy (alloca (len
+ 2), name
);
4640 /* Avoid a somewhat costly call to is_symlink if the filesystem
4641 doesn't support symlinks. */
4642 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4643 is_a_symlink
= is_symlink (name
);
4645 /* Plan A: Open the file and get all the necessary information via
4646 the resulting handle. This solves several issues in one blow:
4648 . retrieves attributes for the target of a symlink, if needed
4649 . gets attributes of root directories and symlinks pointing to
4650 root directories, thus avoiding the need for special-casing
4651 these and detecting them by examining the file-name format
4652 . retrieves more accurate attributes (e.g., non-zero size for
4653 some directories, esp. directories that are junction points)
4654 . correctly resolves "c:/..", "/.." and similar file names
4655 . avoids run-time penalties for 99% of use cases
4657 Plan A is always tried first, unless the user asked not to (but
4658 if the file is a symlink and we need to follow links, we try Plan
4659 A even if the user asked not to).
4661 If Plan A fails, we go to Plan B (below), where various
4662 potentially expensive techniques must be used to handle "special"
4663 files such as UNC volumes etc. */
4664 if (!(NILP (Vw32_get_true_file_attributes
)
4665 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4666 /* Following symlinks requires getting the info by handle. */
4667 || (is_a_symlink
&& follow_symlinks
))
4669 BY_HANDLE_FILE_INFORMATION info
;
4671 if (is_a_symlink
&& !follow_symlinks
)
4672 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4673 /* READ_CONTROL access rights are required to get security info
4674 by handle. But if the OS doesn't support security in the
4675 first place, we don't need to try. */
4676 if (is_windows_9x () != TRUE
)
4677 access_rights
|= READ_CONTROL
;
4679 if (w32_unicode_filenames
)
4681 filename_to_utf16 (name
, name_w
);
4682 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4684 /* If CreateFile fails with READ_CONTROL, try again with
4685 zero as access rights. */
4686 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4687 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4692 filename_to_ansi (name
, name_a
);
4693 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4695 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4696 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4699 if (fh
== INVALID_HANDLE_VALUE
)
4700 goto no_true_file_attributes
;
4702 /* This is more accurate in terms of getting the correct number
4703 of links, but is quite slow (it is noticeable when Emacs is
4704 making a list of file name completions). */
4705 if (GetFileInformationByHandle (fh
, &info
))
4707 nlinks
= info
.nNumberOfLinks
;
4708 /* Might as well use file index to fake inode values, but this
4709 is not guaranteed to be unique unless we keep a handle open
4710 all the time (even then there are situations where it is
4711 not unique). Reputedly, there are at most 48 bits of info
4712 (on NTFS, presumably less on FAT). */
4713 fake_inode
= info
.nFileIndexHigh
;
4715 fake_inode
+= info
.nFileIndexLow
;
4716 serialnum
= info
.dwVolumeSerialNumber
;
4717 fs_high
= info
.nFileSizeHigh
;
4718 fs_low
= info
.nFileSizeLow
;
4719 ctime
= info
.ftCreationTime
;
4720 atime
= info
.ftLastAccessTime
;
4721 wtime
= info
.ftLastWriteTime
;
4722 fattrs
= info
.dwFileAttributes
;
4726 /* We don't go to Plan B here, because it's not clear that
4727 it's a good idea. The only known use case where
4728 CreateFile succeeds, but GetFileInformationByHandle fails
4729 (with ERROR_INVALID_FUNCTION) is for character devices
4730 such as NUL, PRN, etc. For these, switching to Plan B is
4731 a net loss, because we lose the character device
4732 attribute returned by GetFileType below (FindFirstFile
4733 doesn't set that bit in the attributes), and the other
4734 fields don't make sense for character devices anyway.
4735 Emacs doesn't really care for non-file entities in the
4736 context of l?stat, so neither do we. */
4738 /* w32err is assigned so one could put a breakpoint here and
4739 examine its value, when GetFileInformationByHandle
4741 DWORD w32err
= GetLastError ();
4745 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4751 /* Test for a symlink before testing for a directory, since
4752 symlinks to directories have the directory bit set, but we
4753 don't want them to appear as directories. */
4754 if (is_a_symlink
&& !follow_symlinks
)
4755 buf
->st_mode
= S_IFLNK
;
4756 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4757 buf
->st_mode
= S_IFDIR
;
4760 DWORD ftype
= GetFileType (fh
);
4764 case FILE_TYPE_DISK
:
4765 buf
->st_mode
= S_IFREG
;
4767 case FILE_TYPE_PIPE
:
4768 buf
->st_mode
= S_IFIFO
;
4770 case FILE_TYPE_CHAR
:
4771 case FILE_TYPE_UNKNOWN
:
4773 buf
->st_mode
= S_IFCHR
;
4776 /* We produce the fallback owner and group data, based on the
4777 current user that runs Emacs, in the following cases:
4779 . caller didn't request owner and group info
4780 . this is Windows 9X
4781 . getting security by handle failed, and we need to produce
4782 information for the target of a symlink (this is better
4783 than producing a potentially misleading info about the
4786 If getting security by handle fails, and we don't need to
4787 resolve symlinks, we try getting security by name. */
4788 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4789 get_file_owner_and_group (NULL
, buf
);
4792 psd
= get_file_security_desc_by_handle (fh
);
4795 get_file_owner_and_group (psd
, buf
);
4798 else if (!(is_a_symlink
&& follow_symlinks
))
4800 psd
= get_file_security_desc_by_name (name
);
4801 get_file_owner_and_group (psd
, buf
);
4805 get_file_owner_and_group (NULL
, buf
);
4811 no_true_file_attributes
:
4812 /* Plan B: Either getting a handle on the file failed, or the
4813 caller explicitly asked us to not bother making this
4814 information more accurate.
4816 Implementation note: In Plan B, we never bother to resolve
4817 symlinks, even if we got here because we tried Plan A and
4818 failed. That's because, even if the caller asked for extra
4819 precision by setting Vw32_get_true_file_attributes to t,
4820 resolving symlinks requires acquiring a file handle to the
4821 symlink, which we already know will fail. And if the user
4822 did not ask for extra precision, resolving symlinks will fly
4823 in the face of that request, since the user then wants the
4824 lightweight version of the code. */
4825 rootdir
= (path
>= save_name
+ len
- 1
4826 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4828 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4829 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4830 if (IS_DIRECTORY_SEP (r
[0])
4831 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4834 /* Note: If NAME is a symlink to the root of a UNC volume
4835 (i.e. "\\SERVER"), we will not detect that here, and we will
4836 return data about the symlink as result of FindFirst below.
4837 This is unfortunate, but that marginal use case does not
4838 justify a call to chase_symlinks which would impose a penalty
4839 on all the other use cases. (We get here for symlinks to
4840 roots of UNC volumes because CreateFile above fails for them,
4841 unlike with symlinks to root directories X:\ of drives.) */
4842 if (is_unc_volume (name
))
4844 fattrs
= unc_volume_file_attributes (name
);
4848 ctime
= atime
= wtime
= utc_base_ft
;
4852 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4853 strcat (name
, "\\");
4854 if (GetDriveType (name
) < 2)
4860 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4861 ctime
= atime
= wtime
= utc_base_ft
;
4867 if (IS_DIRECTORY_SEP (name
[len
-1]))
4870 /* (This is hacky, but helps when doing file completions on
4871 network drives.) Optimize by using information available from
4872 active readdir if possible. */
4873 len
= strlen (dir_pathname
);
4874 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4876 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4877 && last_dir_find_data
!= -1
4878 && !(is_a_symlink
&& follow_symlinks
)
4879 /* The 2 file-name comparisons below support only ASCII
4880 characters, and will lose (compare not equal) when
4881 the file names include non-ASCII charcaters that are
4882 the same but for the case. However, doing this
4883 properly involves: (a) converting both file names to
4884 UTF-16, (b) lower-casing both names using CharLowerW,
4885 and (c) comparing the results; this would be quite a
4886 bit slower, whereas Plan B is for users who want
4887 lightweight albeit inaccurate version of 'stat'. */
4888 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
4889 && IS_DIRECTORY_SEP (name
[len
])
4890 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4892 have_wfd
= last_dir_find_data
;
4893 /* This was the last entry returned by readdir. */
4894 if (last_dir_find_data
== DIR_FIND_DATA_W
)
4895 wfd_w
= dir_find_data_w
;
4897 wfd_a
= dir_find_data_a
;
4901 logon_network_drive (name
);
4903 if (w32_unicode_filenames
)
4905 filename_to_utf16 (name
, name_w
);
4906 fh
= FindFirstFileW (name_w
, &wfd_w
);
4907 have_wfd
= DIR_FIND_DATA_W
;
4911 filename_to_ansi (name
, name_a
);
4912 /* If NAME includes characters not representable by
4913 the current ANSI codepage, filename_to_ansi
4914 usually replaces them with a '?'. We don't want
4915 to let FindFirstFileA interpret those as widlcards,
4916 and "succeed", returning us data from some random
4917 file in the same directory. */
4918 if (_mbspbrk (name_a
, "?"))
4919 fh
= INVALID_HANDLE_VALUE
;
4921 fh
= FindFirstFileA (name_a
, &wfd_a
);
4922 have_wfd
= DIR_FIND_DATA_A
;
4924 if (fh
== INVALID_HANDLE_VALUE
)
4931 /* Note: if NAME is a symlink, the information we get from
4932 FindFirstFile is for the symlink, not its target. */
4933 if (have_wfd
== DIR_FIND_DATA_W
)
4935 fattrs
= wfd_w
.dwFileAttributes
;
4936 ctime
= wfd_w
.ftCreationTime
;
4937 atime
= wfd_w
.ftLastAccessTime
;
4938 wtime
= wfd_w
.ftLastWriteTime
;
4939 fs_high
= wfd_w
.nFileSizeHigh
;
4940 fs_low
= wfd_w
.nFileSizeLow
;
4944 fattrs
= wfd_a
.dwFileAttributes
;
4945 ctime
= wfd_a
.ftCreationTime
;
4946 atime
= wfd_a
.ftLastAccessTime
;
4947 wtime
= wfd_a
.ftLastWriteTime
;
4948 fs_high
= wfd_a
.nFileSizeHigh
;
4949 fs_low
= wfd_a
.nFileSizeLow
;
4953 serialnum
= volume_info
.serialnum
;
4955 if (is_a_symlink
&& !follow_symlinks
)
4956 buf
->st_mode
= S_IFLNK
;
4957 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4958 buf
->st_mode
= S_IFDIR
;
4960 buf
->st_mode
= S_IFREG
;
4962 get_file_owner_and_group (NULL
, buf
);
4965 buf
->st_ino
= fake_inode
;
4967 buf
->st_dev
= serialnum
;
4968 buf
->st_rdev
= serialnum
;
4970 buf
->st_size
= fs_high
;
4971 buf
->st_size
<<= 32;
4972 buf
->st_size
+= fs_low
;
4973 buf
->st_nlink
= nlinks
;
4975 /* Convert timestamps to Unix format. */
4976 buf
->st_mtime
= convert_time (wtime
);
4977 buf
->st_atime
= convert_time (atime
);
4978 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4979 buf
->st_ctime
= convert_time (ctime
);
4980 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4982 /* determine rwx permissions */
4983 if (is_a_symlink
&& !follow_symlinks
)
4984 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
4987 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
4988 permission
= S_IREAD
;
4990 permission
= S_IREAD
| S_IWRITE
;
4992 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4993 permission
|= S_IEXEC
;
4994 else if (is_exec (name
))
4995 permission
|= S_IEXEC
;
4998 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5004 stat (const char * path
, struct stat
* buf
)
5006 return stat_worker (path
, buf
, 1);
5010 lstat (const char * path
, struct stat
* buf
)
5012 return stat_worker (path
, buf
, 0);
5016 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5018 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5019 This is good enough for the current usage in Emacs, but is fragile.
5021 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5022 Gnulib does this and can serve as a model. */
5023 char fullname
[MAX_UTF8_PATH
];
5027 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5030 errno
= ENAMETOOLONG
;
5036 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5039 /* Provide fstat and utime as well as stat for consistent handling of
5042 fstat (int desc
, struct stat
* buf
)
5044 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5045 BY_HANDLE_FILE_INFORMATION info
;
5046 unsigned __int64 fake_inode
;
5049 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5051 case FILE_TYPE_DISK
:
5052 buf
->st_mode
= S_IFREG
;
5053 if (!GetFileInformationByHandle (fh
, &info
))
5059 case FILE_TYPE_PIPE
:
5060 buf
->st_mode
= S_IFIFO
;
5062 case FILE_TYPE_CHAR
:
5063 case FILE_TYPE_UNKNOWN
:
5065 buf
->st_mode
= S_IFCHR
;
5067 memset (&info
, 0, sizeof (info
));
5068 info
.dwFileAttributes
= 0;
5069 info
.ftCreationTime
= utc_base_ft
;
5070 info
.ftLastAccessTime
= utc_base_ft
;
5071 info
.ftLastWriteTime
= utc_base_ft
;
5074 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5075 buf
->st_mode
= S_IFDIR
;
5077 buf
->st_nlink
= info
.nNumberOfLinks
;
5078 /* Might as well use file index to fake inode values, but this
5079 is not guaranteed to be unique unless we keep a handle open
5080 all the time (even then there are situations where it is
5081 not unique). Reputedly, there are at most 48 bits of info
5082 (on NTFS, presumably less on FAT). */
5083 fake_inode
= info
.nFileIndexHigh
;
5085 fake_inode
+= info
.nFileIndexLow
;
5087 /* MSVC defines _ino_t to be short; other libc's might not. */
5088 if (sizeof (buf
->st_ino
) == 2)
5089 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5091 buf
->st_ino
= fake_inode
;
5093 /* If the caller so requested, get the true file owner and group.
5094 Otherwise, consider the file to belong to the current user. */
5095 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5096 get_file_owner_and_group (NULL
, buf
);
5099 PSECURITY_DESCRIPTOR psd
= NULL
;
5101 psd
= get_file_security_desc_by_handle (fh
);
5104 get_file_owner_and_group (psd
, buf
);
5108 get_file_owner_and_group (NULL
, buf
);
5111 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5112 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5114 buf
->st_size
= info
.nFileSizeHigh
;
5115 buf
->st_size
<<= 32;
5116 buf
->st_size
+= info
.nFileSizeLow
;
5118 /* Convert timestamps to Unix format. */
5119 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5120 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5121 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5122 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5123 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5125 /* determine rwx permissions */
5126 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5127 permission
= S_IREAD
;
5129 permission
= S_IREAD
| S_IWRITE
;
5131 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5132 permission
|= S_IEXEC
;
5135 #if 0 /* no way of knowing the filename */
5136 char * p
= strrchr (name
, '.');
5138 (xstrcasecmp (p
, ".exe") == 0 ||
5139 xstrcasecmp (p
, ".com") == 0 ||
5140 xstrcasecmp (p
, ".bat") == 0 ||
5141 xstrcasecmp (p
, ".cmd") == 0))
5142 permission
|= S_IEXEC
;
5146 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5151 /* A version of 'utime' which handles directories as well as
5155 utime (const char *name
, struct utimbuf
*times
)
5157 struct utimbuf deftime
;
5164 deftime
.modtime
= deftime
.actime
= time (NULL
);
5168 if (w32_unicode_filenames
)
5170 wchar_t name_utf16
[MAX_PATH
];
5172 if (filename_to_utf16 (name
, name_utf16
) != 0)
5173 return -1; /* errno set by filename_to_utf16 */
5175 /* Need write access to set times. */
5176 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5177 /* If NAME specifies a directory, FILE_SHARE_DELETE
5178 allows other processes to delete files inside it,
5179 while we have the directory open. */
5180 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5181 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5185 char name_ansi
[MAX_PATH
];
5187 if (filename_to_ansi (name
, name_ansi
) != 0)
5188 return -1; /* errno set by filename_to_ansi */
5190 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5191 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5192 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5194 if (fh
!= INVALID_HANDLE_VALUE
)
5196 convert_from_time_t (times
->actime
, &atime
);
5197 convert_from_time_t (times
->modtime
, &mtime
);
5198 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5208 DWORD err
= GetLastError ();
5212 case ERROR_FILE_NOT_FOUND
:
5213 case ERROR_PATH_NOT_FOUND
:
5214 case ERROR_INVALID_DRIVE
:
5215 case ERROR_BAD_NETPATH
:
5216 case ERROR_DEV_NOT_EXIST
:
5217 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5218 file name includes ?s, i.e. translation to ANSI failed. */
5219 case ERROR_INVALID_NAME
:
5222 case ERROR_TOO_MANY_OPEN_FILES
:
5225 case ERROR_ACCESS_DENIED
:
5226 case ERROR_SHARING_VIOLATION
:
5239 /* Symlink-related functions. */
5240 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5241 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5245 symlink (char const *filename
, char const *linkname
)
5247 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5249 int dir_access
, filename_ends_in_slash
;
5251 /* Diagnostics follows Posix as much as possible. */
5252 if (filename
== NULL
|| linkname
== NULL
)
5262 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5264 errno
= ENAMETOOLONG
;
5268 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5269 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5275 /* Note: since empty FILENAME was already rejected, we can safely
5276 refer to FILENAME[1]. */
5277 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5279 /* Non-absolute FILENAME is understood as being relative to
5280 LINKNAME's directory. We need to prepend that directory to
5281 FILENAME to get correct results from faccessat below, since
5282 otherwise it will interpret FILENAME relative to the
5283 directory where the Emacs process runs. Note that
5284 make-symbolic-link always makes sure LINKNAME is a fully
5285 expanded file name. */
5286 char tem
[MAX_UTF8_PATH
];
5287 char *p
= linkfn
+ strlen (linkfn
);
5289 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5292 strncpy (tem
, linkfn
, p
- linkfn
);
5293 tem
[p
- linkfn
] = '\0';
5294 strcat (tem
, filename
);
5295 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5298 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5300 /* Since Windows distinguishes between symlinks to directories and
5301 to files, we provide a kludgy feature: if FILENAME doesn't
5302 exist, but ends in a slash, we create a symlink to directory. If
5303 FILENAME exists and is a directory, we always create a symlink to
5305 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5306 if (dir_access
== 0 || filename_ends_in_slash
)
5307 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5309 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5310 if (filename_ends_in_slash
)
5311 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5314 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5316 /* ENOSYS is set by create_symbolic_link, when it detects that
5317 the OS doesn't support the CreateSymbolicLink API. */
5318 if (errno
!= ENOSYS
)
5320 DWORD w32err
= GetLastError ();
5324 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5325 TGTFN point to the same file name, go figure. */
5327 case ERROR_FILE_EXISTS
:
5330 case ERROR_ACCESS_DENIED
:
5333 case ERROR_FILE_NOT_FOUND
:
5334 case ERROR_PATH_NOT_FOUND
:
5335 case ERROR_BAD_NETPATH
:
5336 case ERROR_INVALID_REPARSE_DATA
:
5339 case ERROR_DIRECTORY
:
5342 case ERROR_PRIVILEGE_NOT_HELD
:
5343 case ERROR_NOT_ALL_ASSIGNED
:
5346 case ERROR_DISK_FULL
:
5359 /* A quick inexpensive test of whether FILENAME identifies a file that
5360 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5361 must already be in the normalized form returned by
5364 Note: for repeated operations on many files, it is best to test
5365 whether the underlying volume actually supports symlinks, by
5366 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5367 avoid the call to this function if it doesn't. That's because the
5368 call to GetFileAttributes takes a non-negligible time, especially
5369 on non-local or removable filesystems. See stat_worker for an
5370 example of how to do that. */
5372 is_symlink (const char *filename
)
5375 wchar_t filename_w
[MAX_PATH
];
5376 char filename_a
[MAX_PATH
];
5377 WIN32_FIND_DATAW wfdw
;
5378 WIN32_FIND_DATAA wfda
;
5380 int attrs_mean_symlink
;
5382 if (w32_unicode_filenames
)
5384 filename_to_utf16 (filename
, filename_w
);
5385 attrs
= GetFileAttributesW (filename_w
);
5389 filename_to_ansi (filename
, filename_a
);
5390 attrs
= GetFileAttributesA (filename_a
);
5394 DWORD w32err
= GetLastError ();
5398 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5400 case ERROR_ACCESS_DENIED
:
5403 case ERROR_FILE_NOT_FOUND
:
5404 case ERROR_PATH_NOT_FOUND
:
5411 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5413 logon_network_drive (filename
);
5414 if (w32_unicode_filenames
)
5416 fh
= FindFirstFileW (filename_w
, &wfdw
);
5417 attrs_mean_symlink
=
5418 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5419 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5421 else if (_mbspbrk (filename_a
, "?"))
5423 /* filename_to_ansi failed to convert the file name. */
5429 fh
= FindFirstFileA (filename_a
, &wfda
);
5430 attrs_mean_symlink
=
5431 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5432 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5434 if (fh
== INVALID_HANDLE_VALUE
)
5437 return attrs_mean_symlink
;
5440 /* If NAME identifies a symbolic link, copy into BUF the file name of
5441 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5442 null-terminate the target name, even if it fits. Return the number
5443 of bytes copied, or -1 if NAME is not a symlink or any error was
5444 encountered while resolving it. The file name copied into BUF is
5445 encoded in the current ANSI codepage. */
5447 readlink (const char *name
, char *buf
, size_t buf_size
)
5450 TOKEN_PRIVILEGES privs
;
5451 int restore_privs
= 0;
5454 char resolved
[MAX_UTF8_PATH
];
5467 path
= map_w32_filename (name
, NULL
);
5469 if (strlen (path
) > MAX_UTF8_PATH
)
5471 errno
= ENAMETOOLONG
;
5476 if (is_windows_9x () == TRUE
5477 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5478 || !is_symlink (path
))
5481 errno
= EINVAL
; /* not a symlink */
5485 /* Done with simple tests, now we're in for some _real_ work. */
5486 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5488 /* Implementation note: From here and onward, don't return early,
5489 since that will fail to restore the original set of privileges of
5490 the calling thread. */
5492 retval
= -1; /* not too optimistic, are we? */
5494 /* Note: In the next call to CreateFile, we use zero as the 2nd
5495 argument because, when the symlink is a hidden/system file,
5496 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5497 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5498 and directory symlinks. */
5499 if (w32_unicode_filenames
)
5501 wchar_t path_w
[MAX_PATH
];
5503 filename_to_utf16 (path
, path_w
);
5504 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5505 FILE_FLAG_OPEN_REPARSE_POINT
5506 | FILE_FLAG_BACKUP_SEMANTICS
,
5511 char path_a
[MAX_PATH
];
5513 filename_to_ansi (path
, path_a
);
5514 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5515 FILE_FLAG_OPEN_REPARSE_POINT
5516 | FILE_FLAG_BACKUP_SEMANTICS
,
5519 if (sh
!= INVALID_HANDLE_VALUE
)
5521 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5522 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5525 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5526 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5529 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5533 /* Copy the link target name, in wide characters, from
5534 reparse_data, then convert it to multibyte encoding in
5535 the current locale's codepage. */
5539 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5541 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5542 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5543 size_t size_to_copy
= buf_size
;
5545 /* According to MSDN, PrintNameLength does not include the
5546 terminating null character. */
5547 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5548 memcpy (lwname
, lwname_src
, lwname_len
);
5549 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5550 filename_from_utf16 (lwname
, resolved
);
5551 dostounix_filename (resolved
);
5552 lname_size
= strlen (resolved
) + 1;
5553 if (lname_size
<= buf_size
)
5554 size_to_copy
= lname_size
;
5555 strncpy (buf
, resolved
, size_to_copy
);
5557 retval
= size_to_copy
;
5563 /* CreateFile failed. */
5564 DWORD w32err2
= GetLastError ();
5568 case ERROR_FILE_NOT_FOUND
:
5569 case ERROR_PATH_NOT_FOUND
:
5572 case ERROR_ACCESS_DENIED
:
5573 case ERROR_TOO_MANY_OPEN_FILES
:
5583 restore_privilege (&privs
);
5591 readlinkat (int fd
, char const *name
, char *buffer
,
5594 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5595 as in fstatat. FIXME: Add proper support for readlinkat. */
5596 char fullname
[MAX_UTF8_PATH
];
5600 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5603 errno
= ENAMETOOLONG
;
5609 return readlink (name
, buffer
, buffer_size
);
5612 /* If FILE is a symlink, return its target (stored in a static
5613 buffer); otherwise return FILE.
5615 This function repeatedly resolves symlinks in the last component of
5616 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5617 until it arrives at a file whose last component is not a symlink,
5618 or some error occurs. It returns the target of the last
5619 successfully resolved symlink in the chain. If it succeeds to
5620 resolve even a single symlink, the value returned is an absolute
5621 file name with backslashes (result of GetFullPathName). By
5622 contrast, if the original FILE is returned, it is unaltered.
5624 Note: This function can set errno even if it succeeds.
5626 Implementation note: we only resolve the last portion ("basename")
5627 of the argument FILE and of each following file in the chain,
5628 disregarding any possible symlinks in its leading directories.
5629 This is because Windows system calls and library functions
5630 transparently resolve symlinks in leading directories and return
5631 correct information, as long as the basename is not a symlink. */
5633 chase_symlinks (const char *file
)
5635 static char target
[MAX_UTF8_PATH
];
5636 char link
[MAX_UTF8_PATH
];
5637 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5638 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5639 ssize_t res
, link_len
;
5642 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5643 return (char *)file
;
5645 if (w32_unicode_filenames
)
5647 wchar_t file_w
[MAX_PATH
];
5649 filename_to_utf16 (file
, file_w
);
5650 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5651 return (char *)file
;
5652 filename_from_utf16 (link_w
, link
);
5656 char file_a
[MAX_PATH
];
5658 filename_to_ansi (file
, file_a
);
5659 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5660 return (char *)file
;
5661 filename_from_ansi (link_a
, link
);
5663 link_len
= strlen (link
);
5668 /* Remove trailing slashes, as we want to resolve the last
5669 non-trivial part of the link name. */
5670 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5671 link
[link_len
--] = '\0';
5673 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5677 if (!(IS_DEVICE_SEP (target
[1])
5678 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5680 /* Target is relative. Append it to the directory part of
5681 the symlink, then copy the result back to target. */
5682 char *p
= link
+ link_len
;
5684 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5687 strcpy (target
, link
);
5689 /* Resolve any "." and ".." to get a fully-qualified file name
5691 if (w32_unicode_filenames
)
5693 filename_to_utf16 (target
, target_w
);
5694 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5696 filename_from_utf16 (link_w
, link
);
5700 filename_to_ansi (target
, target_a
);
5701 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5703 filename_from_ansi (link_a
, link
);
5705 link_len
= strlen (link
);
5707 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5709 if (loop_count
> 100)
5712 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5713 return (char *)file
;
5718 /* Posix ACL emulation. */
5721 acl_valid (acl_t acl
)
5723 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5727 acl_to_text (acl_t acl
, ssize_t
*size
)
5730 SECURITY_INFORMATION flags
=
5731 OWNER_SECURITY_INFORMATION
|
5732 GROUP_SECURITY_INFORMATION
|
5733 DACL_SECURITY_INFORMATION
;
5734 char *retval
= NULL
;
5740 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5743 /* We don't want to mix heaps, so we duplicate the string in our
5744 heap and free the one allocated by the API. */
5745 retval
= xstrdup (str_acl
);
5748 LocalFree (str_acl
);
5750 else if (errno
!= ENOTSUP
)
5757 acl_from_text (const char *acl_str
)
5759 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5765 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5768 retval
= xmalloc (sd_size
);
5769 memcpy (retval
, psd
, sd_size
);
5772 else if (errno
!= ENOTSUP
)
5779 acl_free (void *ptr
)
5786 acl_get_file (const char *fname
, acl_type_t type
)
5788 PSECURITY_DESCRIPTOR psd
= NULL
;
5789 const char *filename
;
5791 if (type
== ACL_TYPE_ACCESS
)
5794 SECURITY_INFORMATION si
=
5795 OWNER_SECURITY_INFORMATION
|
5796 GROUP_SECURITY_INFORMATION
|
5797 DACL_SECURITY_INFORMATION
;
5800 filename
= map_w32_filename (fname
, NULL
);
5801 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5802 fname
= chase_symlinks (filename
);
5807 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5808 && errno
!= ENOTSUP
)
5810 err
= GetLastError ();
5811 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5813 psd
= xmalloc (sd_len
);
5814 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5821 else if (err
== ERROR_FILE_NOT_FOUND
5822 || err
== ERROR_PATH_NOT_FOUND
5823 /* ERROR_INVALID_NAME is what we get if
5824 w32-unicode-filenames is nil and the file cannot
5825 be encoded in the current ANSI codepage. */
5826 || err
== ERROR_INVALID_NAME
)
5834 else if (type
!= ACL_TYPE_DEFAULT
)
5841 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5843 TOKEN_PRIVILEGES old1
, old2
;
5845 int st
= 0, retval
= -1;
5846 SECURITY_INFORMATION flags
= 0;
5852 const char *filename
;
5854 if (acl_valid (acl
) != 0
5855 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5861 if (type
== ACL_TYPE_DEFAULT
)
5867 filename
= map_w32_filename (fname
, NULL
);
5868 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5869 fname
= chase_symlinks (filename
);
5873 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5875 flags
|= OWNER_SECURITY_INFORMATION
;
5876 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5878 flags
|= GROUP_SECURITY_INFORMATION
;
5879 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5882 flags
|= DACL_SECURITY_INFORMATION
;
5886 /* According to KB-245153, setting the owner will succeed if either:
5887 (1) the caller is the user who will be the new owner, and has the
5888 SE_TAKE_OWNERSHIP privilege, or
5889 (2) the caller has the SE_RESTORE privilege, in which case she can
5890 set any valid user or group as the owner
5892 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5893 privileges, and disregard any failures in obtaining them. If
5894 these privileges cannot be obtained, and do not already exist in
5895 the calling thread's security token, this function could fail
5897 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5899 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5904 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5906 err
= GetLastError ();
5908 if (errno
== ENOTSUP
)
5910 else if (err
== ERROR_INVALID_OWNER
5911 || err
== ERROR_NOT_ALL_ASSIGNED
5912 || err
== ERROR_ACCESS_DENIED
)
5914 /* Maybe the requested ACL and the one the file already has
5915 are identical, in which case we can silently ignore the
5916 failure. (And no, Windows doesn't.) */
5917 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5922 char *acl_from
= acl_to_text (current_acl
, NULL
);
5923 char *acl_to
= acl_to_text (acl
, NULL
);
5925 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5931 acl_free (acl_from
);
5934 acl_free (current_acl
);
5937 else if (err
== ERROR_FILE_NOT_FOUND
5938 || err
== ERROR_PATH_NOT_FOUND
5939 /* ERROR_INVALID_NAME is what we get if
5940 w32-unicode-filenames is nil and the file cannot be
5941 encoded in the current ANSI codepage. */
5942 || err
== ERROR_INVALID_NAME
)
5956 restore_privilege (&old2
);
5957 restore_privilege (&old1
);
5965 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5966 have a fixed max size for file names, so we don't need the kind of
5967 alloc/malloc/realloc dance the gnulib version does. We also don't
5968 support FD-relative symlinks. */
5970 careadlinkat (int fd
, char const *filename
,
5971 char *buffer
, size_t buffer_size
,
5972 struct allocator
const *alloc
,
5973 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
5975 char linkname
[MAX_UTF8_PATH
];
5978 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
5982 char *retval
= buffer
;
5984 linkname
[link_size
++] = '\0';
5985 if (link_size
> buffer_size
)
5986 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
5988 memcpy (retval
, linkname
, link_size
);
5996 /* Support for browsing other processes and their attributes. See
5997 process.c for the Lisp bindings. */
5999 /* Helper wrapper functions. */
6001 static HANDLE WINAPI
6002 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6004 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6006 if (g_b_init_create_toolhelp32_snapshot
== 0)
6008 g_b_init_create_toolhelp32_snapshot
= 1;
6009 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6010 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6011 "CreateToolhelp32Snapshot");
6013 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6015 return INVALID_HANDLE_VALUE
;
6017 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6021 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6023 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6025 if (g_b_init_process32_first
== 0)
6027 g_b_init_process32_first
= 1;
6028 s_pfn_Process32_First
= (Process32First_Proc
)
6029 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6032 if (s_pfn_Process32_First
== NULL
)
6036 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6040 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6042 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6044 if (g_b_init_process32_next
== 0)
6046 g_b_init_process32_next
= 1;
6047 s_pfn_Process32_Next
= (Process32Next_Proc
)
6048 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6051 if (s_pfn_Process32_Next
== NULL
)
6055 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6059 open_thread_token (HANDLE ThreadHandle
,
6060 DWORD DesiredAccess
,
6062 PHANDLE TokenHandle
)
6064 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6065 HMODULE hm_advapi32
= NULL
;
6066 if (is_windows_9x () == TRUE
)
6068 SetLastError (ERROR_NOT_SUPPORTED
);
6071 if (g_b_init_open_thread_token
== 0)
6073 g_b_init_open_thread_token
= 1;
6074 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6075 s_pfn_Open_Thread_Token
=
6076 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6078 if (s_pfn_Open_Thread_Token
== NULL
)
6080 SetLastError (ERROR_NOT_SUPPORTED
);
6084 s_pfn_Open_Thread_Token (
6093 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6095 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6096 HMODULE hm_advapi32
= NULL
;
6097 if (is_windows_9x () == TRUE
)
6101 if (g_b_init_impersonate_self
== 0)
6103 g_b_init_impersonate_self
= 1;
6104 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6105 s_pfn_Impersonate_Self
=
6106 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6108 if (s_pfn_Impersonate_Self
== NULL
)
6112 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6116 revert_to_self (void)
6118 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6119 HMODULE hm_advapi32
= NULL
;
6120 if (is_windows_9x () == TRUE
)
6124 if (g_b_init_revert_to_self
== 0)
6126 g_b_init_revert_to_self
= 1;
6127 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6128 s_pfn_Revert_To_Self
=
6129 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6131 if (s_pfn_Revert_To_Self
== NULL
)
6135 return s_pfn_Revert_To_Self ();
6139 get_process_memory_info (HANDLE h_proc
,
6140 PPROCESS_MEMORY_COUNTERS mem_counters
,
6143 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6144 HMODULE hm_psapi
= NULL
;
6145 if (is_windows_9x () == TRUE
)
6149 if (g_b_init_get_process_memory_info
== 0)
6151 g_b_init_get_process_memory_info
= 1;
6152 hm_psapi
= LoadLibrary ("Psapi.dll");
6154 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6155 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6157 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6161 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6165 get_process_working_set_size (HANDLE h_proc
,
6169 static GetProcessWorkingSetSize_Proc
6170 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6172 if (is_windows_9x () == TRUE
)
6176 if (g_b_init_get_process_working_set_size
== 0)
6178 g_b_init_get_process_working_set_size
= 1;
6179 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6180 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6181 "GetProcessWorkingSetSize");
6183 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6187 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6191 global_memory_status (MEMORYSTATUS
*buf
)
6193 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6195 if (is_windows_9x () == TRUE
)
6199 if (g_b_init_global_memory_status
== 0)
6201 g_b_init_global_memory_status
= 1;
6202 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6203 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6204 "GlobalMemoryStatus");
6206 if (s_pfn_Global_Memory_Status
== NULL
)
6210 return s_pfn_Global_Memory_Status (buf
);
6214 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6216 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6218 if (is_windows_9x () == TRUE
)
6222 if (g_b_init_global_memory_status_ex
== 0)
6224 g_b_init_global_memory_status_ex
= 1;
6225 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6226 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6227 "GlobalMemoryStatusEx");
6229 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6233 return s_pfn_Global_Memory_Status_Ex (buf
);
6237 list_system_processes (void)
6239 struct gcpro gcpro1
;
6240 Lisp_Object proclist
= Qnil
;
6243 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6245 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6247 PROCESSENTRY32 proc_entry
;
6253 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6254 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6255 res
= process32_next (h_snapshot
, &proc_entry
))
6257 proc_id
= proc_entry
.th32ProcessID
;
6258 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6261 CloseHandle (h_snapshot
);
6263 proclist
= Fnreverse (proclist
);
6270 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6272 TOKEN_PRIVILEGES priv
;
6273 DWORD priv_size
= sizeof (priv
);
6274 DWORD opriv_size
= sizeof (*old_priv
);
6275 HANDLE h_token
= NULL
;
6276 HANDLE h_thread
= GetCurrentThread ();
6280 res
= open_thread_token (h_thread
,
6281 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6283 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6285 if (impersonate_self (SecurityImpersonation
))
6286 res
= open_thread_token (h_thread
,
6287 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6292 priv
.PrivilegeCount
= 1;
6293 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6294 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6295 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6296 old_priv
, &opriv_size
)
6297 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6301 CloseHandle (h_token
);
6307 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6309 DWORD priv_size
= sizeof (*priv
);
6310 HANDLE h_token
= NULL
;
6313 if (open_thread_token (GetCurrentThread (),
6314 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6317 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6318 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6322 CloseHandle (h_token
);
6328 ltime (ULONGLONG time_100ns
)
6330 ULONGLONG time_sec
= time_100ns
/ 10000000;
6331 int subsec
= time_100ns
% 10000000;
6332 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6333 subsec
/ 10, subsec
% 10 * 100000);
6336 #define U64_TO_LISP_TIME(time) ltime (time)
6339 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6340 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6343 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6344 ULONGLONG tem1
, tem2
, tem3
, tem
;
6347 || !get_process_times_fn
6348 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6349 &ft_kernel
, &ft_user
))
6352 GetSystemTimeAsFileTime (&ft_current
);
6354 FILETIME_TO_U64 (tem1
, ft_kernel
);
6355 *stime
= U64_TO_LISP_TIME (tem1
);
6357 FILETIME_TO_U64 (tem2
, ft_user
);
6358 *utime
= U64_TO_LISP_TIME (tem2
);
6361 *ttime
= U64_TO_LISP_TIME (tem3
);
6363 FILETIME_TO_U64 (tem
, ft_creation
);
6364 /* Process no 4 (System) returns zero creation time. */
6367 *ctime
= U64_TO_LISP_TIME (tem
);
6371 FILETIME_TO_U64 (tem3
, ft_current
);
6372 tem
= (tem3
- utc_base
) - tem
;
6374 *etime
= U64_TO_LISP_TIME (tem
);
6378 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6389 system_process_attributes (Lisp_Object pid
)
6391 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6392 Lisp_Object attrs
= Qnil
;
6393 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6394 HANDLE h_snapshot
, h_proc
;
6397 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6398 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6399 DWORD glength
= sizeof (gname
);
6400 HANDLE token
= NULL
;
6401 SID_NAME_USE user_type
;
6402 unsigned char *buf
= NULL
;
6404 TOKEN_USER user_token
;
6405 TOKEN_PRIMARY_GROUP group_token
;
6408 PROCESS_MEMORY_COUNTERS mem
;
6409 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6410 SIZE_T minrss
, maxrss
;
6412 MEMORY_STATUS_EX memstex
;
6413 double totphys
= 0.0;
6414 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6416 BOOL result
= FALSE
;
6418 CHECK_NUMBER_OR_FLOAT (pid
);
6419 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6421 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6423 GCPRO3 (attrs
, decoded_cmd
, tem
);
6425 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6430 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6431 for (res
= process32_first (h_snapshot
, &pe
); res
;
6432 res
= process32_next (h_snapshot
, &pe
))
6434 if (proc_id
== pe
.th32ProcessID
)
6437 decoded_cmd
= build_string ("Idle");
6440 /* Decode the command name from locale-specific
6442 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6445 code_convert_string_norecord (cmd_str
,
6446 Vlocale_coding_system
, 0);
6448 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6449 attrs
= Fcons (Fcons (Qppid
,
6450 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6452 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6454 attrs
= Fcons (Fcons (Qthcount
,
6455 make_fixnum_or_float (pe
.cntThreads
)),
6462 CloseHandle (h_snapshot
);
6471 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6473 /* If we were denied a handle to the process, try again after
6474 enabling the SeDebugPrivilege in our process. */
6477 TOKEN_PRIVILEGES priv_current
;
6479 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6481 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6483 restore_privilege (&priv_current
);
6489 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6492 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6493 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6495 buf
= xmalloc (blen
);
6496 result
= get_token_information (token
, TokenUser
,
6497 (LPVOID
)buf
, blen
, &needed
);
6500 memcpy (&user_token
, buf
, sizeof (user_token
));
6501 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6503 euid
= get_rid (user_token
.User
.Sid
);
6504 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6509 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6512 strcpy (uname
, "unknown");
6516 ulength
= strlen (uname
);
6522 /* Determine a reasonable euid and gid values. */
6523 if (xstrcasecmp ("administrator", uname
) == 0)
6525 euid
= 500; /* well-known Administrator uid */
6526 egid
= 513; /* well-known None gid */
6530 /* Get group id and name. */
6531 result
= get_token_information (token
, TokenPrimaryGroup
,
6532 (LPVOID
)buf
, blen
, &needed
);
6533 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6535 buf
= xrealloc (buf
, blen
= needed
);
6536 result
= get_token_information (token
, TokenPrimaryGroup
,
6537 (LPVOID
)buf
, blen
, &needed
);
6541 memcpy (&group_token
, buf
, sizeof (group_token
));
6542 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6544 egid
= get_rid (group_token
.PrimaryGroup
);
6545 dlength
= sizeof (domain
);
6547 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6548 gname
, &glength
, NULL
, &dlength
,
6551 w32_add_to_cache (group_token
.PrimaryGroup
,
6555 strcpy (gname
, "None");
6559 glength
= strlen (gname
);
6567 if (!is_windows_9x ())
6569 /* We couldn't open the process token, presumably because of
6570 insufficient access rights. Assume this process is run
6572 strcpy (uname
, "SYSTEM");
6573 strcpy (gname
, "None");
6574 euid
= 18; /* SYSTEM */
6575 egid
= 513; /* None */
6576 glength
= strlen (gname
);
6577 ulength
= strlen (uname
);
6579 /* If we are running under Windows 9X, where security calls are
6580 not supported, we assume all processes are run by the current
6582 else if (GetUserName (uname
, &ulength
))
6584 if (xstrcasecmp ("administrator", uname
) == 0)
6589 strcpy (gname
, "None");
6590 glength
= strlen (gname
);
6591 ulength
= strlen (uname
);
6597 strcpy (uname
, "administrator");
6598 ulength
= strlen (uname
);
6599 strcpy (gname
, "None");
6600 glength
= strlen (gname
);
6603 CloseHandle (token
);
6606 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6607 tem
= make_unibyte_string (uname
, ulength
);
6608 attrs
= Fcons (Fcons (Quser
,
6609 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6611 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6612 tem
= make_unibyte_string (gname
, glength
);
6613 attrs
= Fcons (Fcons (Qgroup
,
6614 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6617 if (global_memory_status_ex (&memstex
))
6618 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6619 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6621 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6622 double, so we need to do this for it... */
6624 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6625 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6626 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6628 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6630 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6631 else if (global_memory_status (&memst
))
6632 totphys
= memst
.dwTotalPhys
/ 1024.0;
6635 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6638 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6640 attrs
= Fcons (Fcons (Qmajflt
,
6641 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6643 attrs
= Fcons (Fcons (Qvsize
,
6644 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6646 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6648 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6651 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6653 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6655 attrs
= Fcons (Fcons (Qmajflt
,
6656 make_fixnum_or_float (mem
.PageFaultCount
)),
6658 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6660 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6663 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6665 DWORD rss
= maxrss
/ 1024;
6667 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6669 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6672 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6674 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6675 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6676 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6677 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6678 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6679 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6682 /* FIXME: Retrieve command line by walking the PEB of the process. */
6685 CloseHandle (h_proc
);
6691 /* Wrappers for winsock functions to map between our file descriptors
6692 and winsock's handles; also set h_errno for convenience.
6694 To allow Emacs to run on systems which don't have winsock support
6695 installed, we dynamically link to winsock on startup if present, and
6696 otherwise provide the minimum necessary functionality
6697 (eg. gethostname). */
6699 /* function pointers for relevant socket functions */
6700 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6701 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6702 int (PASCAL
*pfn_WSAGetLastError
) (void);
6703 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6704 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6705 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6706 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6707 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6708 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6709 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6710 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6711 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6712 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6713 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6714 int (PASCAL
*pfn_WSACleanup
) (void);
6716 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6717 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6718 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6719 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6720 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6721 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6722 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6723 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6724 const char * optval
, int optlen
);
6725 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6726 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6728 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6729 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6730 struct sockaddr
* from
, int * fromlen
);
6731 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6732 const struct sockaddr
* to
, int tolen
);
6734 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6735 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6736 #ifndef HANDLE_FLAG_INHERIT
6737 #define HANDLE_FLAG_INHERIT 1
6741 static int winsock_inuse
;
6746 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6748 release_listen_threads ();
6749 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6750 after WSAStartup returns successfully, but it seems reasonable
6751 to allow unloading winsock anyway in that case. */
6752 if (pfn_WSACleanup () == 0 ||
6753 pfn_WSAGetLastError () == WSAENETDOWN
)
6755 if (FreeLibrary (winsock_lib
))
6764 init_winsock (int load_now
)
6766 WSADATA winsockData
;
6768 if (winsock_lib
!= NULL
)
6771 pfn_SetHandleInformation
6772 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6773 "SetHandleInformation");
6775 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6777 if (winsock_lib
!= NULL
)
6779 /* dynamically link to socket functions */
6781 #define LOAD_PROC(fn) \
6782 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6785 LOAD_PROC (WSAStartup
);
6786 LOAD_PROC (WSASetLastError
);
6787 LOAD_PROC (WSAGetLastError
);
6788 LOAD_PROC (WSAEventSelect
);
6789 LOAD_PROC (WSACreateEvent
);
6790 LOAD_PROC (WSACloseEvent
);
6793 LOAD_PROC (connect
);
6794 LOAD_PROC (ioctlsocket
);
6797 LOAD_PROC (closesocket
);
6798 LOAD_PROC (shutdown
);
6801 LOAD_PROC (inet_addr
);
6802 LOAD_PROC (gethostname
);
6803 LOAD_PROC (gethostbyname
);
6804 LOAD_PROC (getservbyname
);
6805 LOAD_PROC (getpeername
);
6806 LOAD_PROC (WSACleanup
);
6807 LOAD_PROC (setsockopt
);
6809 LOAD_PROC (getsockname
);
6811 LOAD_PROC (recvfrom
);
6815 /* specify version 1.1 of winsock */
6816 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6818 if (winsockData
.wVersion
!= 0x101)
6823 /* Report that winsock exists and is usable, but leave
6824 socket functions disabled. I am assuming that calling
6825 WSAStartup does not require any network interaction,
6826 and in particular does not cause or require a dial-up
6827 connection to be established. */
6830 FreeLibrary (winsock_lib
);
6838 FreeLibrary (winsock_lib
);
6848 /* Function to map winsock error codes to errno codes for those errno
6849 code defined in errno.h (errno values not defined by errno.h are
6850 already in nt/inc/sys/socket.h). */
6857 if (winsock_lib
== NULL
)
6860 wsa_err
= pfn_WSAGetLastError ();
6864 case WSAEACCES
: errno
= EACCES
; break;
6865 case WSAEBADF
: errno
= EBADF
; break;
6866 case WSAEFAULT
: errno
= EFAULT
; break;
6867 case WSAEINTR
: errno
= EINTR
; break;
6868 case WSAEINVAL
: errno
= EINVAL
; break;
6869 case WSAEMFILE
: errno
= EMFILE
; break;
6870 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
6871 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
6872 default: errno
= wsa_err
; break;
6880 if (winsock_lib
!= NULL
)
6881 pfn_WSASetLastError (0);
6884 /* Extend strerror to handle the winsock-specific error codes. */
6888 } _wsa_errlist
[] = {
6889 {WSAEINTR
, "Interrupted function call"},
6890 {WSAEBADF
, "Bad file descriptor"},
6891 {WSAEACCES
, "Permission denied"},
6892 {WSAEFAULT
, "Bad address"},
6893 {WSAEINVAL
, "Invalid argument"},
6894 {WSAEMFILE
, "Too many open files"},
6896 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
6897 {WSAEINPROGRESS
, "Operation now in progress"},
6898 {WSAEALREADY
, "Operation already in progress"},
6899 {WSAENOTSOCK
, "Socket operation on non-socket"},
6900 {WSAEDESTADDRREQ
, "Destination address required"},
6901 {WSAEMSGSIZE
, "Message too long"},
6902 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
6903 {WSAENOPROTOOPT
, "Bad protocol option"},
6904 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
6905 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
6906 {WSAEOPNOTSUPP
, "Operation not supported"},
6907 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
6908 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
6909 {WSAEADDRINUSE
, "Address already in use"},
6910 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
6911 {WSAENETDOWN
, "Network is down"},
6912 {WSAENETUNREACH
, "Network is unreachable"},
6913 {WSAENETRESET
, "Network dropped connection on reset"},
6914 {WSAECONNABORTED
, "Software caused connection abort"},
6915 {WSAECONNRESET
, "Connection reset by peer"},
6916 {WSAENOBUFS
, "No buffer space available"},
6917 {WSAEISCONN
, "Socket is already connected"},
6918 {WSAENOTCONN
, "Socket is not connected"},
6919 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
6920 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
6921 {WSAETIMEDOUT
, "Connection timed out"},
6922 {WSAECONNREFUSED
, "Connection refused"},
6923 {WSAELOOP
, "Network loop"}, /* not sure */
6924 {WSAENAMETOOLONG
, "Name is too long"},
6925 {WSAEHOSTDOWN
, "Host is down"},
6926 {WSAEHOSTUNREACH
, "No route to host"},
6927 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
6928 {WSAEPROCLIM
, "Too many processes"},
6929 {WSAEUSERS
, "Too many users"}, /* not sure */
6930 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
6931 {WSAESTALE
, "Data is stale"}, /* not sure */
6932 {WSAEREMOTE
, "Remote error"}, /* not sure */
6934 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
6935 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
6936 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
6937 {WSAEDISCON
, "Graceful shutdown in progress"},
6939 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
6940 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
6941 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
6942 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
6943 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
6944 {WSASYSCALLFAILURE
, "System call failure"},
6945 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
6946 {WSATYPE_NOT_FOUND
, "Class type not found"},
6947 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
6948 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
6949 {WSAEREFUSED
, "Operation refused"}, /* not sure */
6952 {WSAHOST_NOT_FOUND
, "Host not found"},
6953 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
6954 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
6955 {WSANO_DATA
, "Valid name, no data record of requested type"},
6961 sys_strerror (int error_no
)
6964 static char unknown_msg
[40];
6966 if (error_no
>= 0 && error_no
< sys_nerr
)
6967 return sys_errlist
[error_no
];
6969 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
6970 if (_wsa_errlist
[i
].errnum
== error_no
)
6971 return _wsa_errlist
[i
].msg
;
6973 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
6977 /* [andrewi 3-May-96] I've had conflicting results using both methods,
6978 but I believe the method of keeping the socket handle separate (and
6979 insuring it is not inheritable) is the correct one. */
6981 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
6983 static int socket_to_fd (SOCKET s
);
6986 sys_socket (int af
, int type
, int protocol
)
6990 if (winsock_lib
== NULL
)
6993 return INVALID_SOCKET
;
6998 /* call the real socket function */
6999 s
= pfn_socket (af
, type
, protocol
);
7001 if (s
!= INVALID_SOCKET
)
7002 return socket_to_fd (s
);
7008 /* Convert a SOCKET to a file descriptor. */
7010 socket_to_fd (SOCKET s
)
7015 /* Although under NT 3.5 _open_osfhandle will accept a socket
7016 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7017 that does not work under NT 3.1. However, we can get the same
7018 effect by using a backdoor function to replace an existing
7019 descriptor handle with the one we want. */
7021 /* allocate a file descriptor (with appropriate flags) */
7022 fd
= _open ("NUL:", _O_RDWR
);
7025 /* Make a non-inheritable copy of the socket handle. Note
7026 that it is possible that sockets aren't actually kernel
7027 handles, which appears to be the case on Windows 9x when
7028 the MS Proxy winsock client is installed. */
7030 /* Apparently there is a bug in NT 3.51 with some service
7031 packs, which prevents using DuplicateHandle to make a
7032 socket handle non-inheritable (causes WSACleanup to
7033 hang). The work-around is to use SetHandleInformation
7034 instead if it is available and implemented. */
7035 if (pfn_SetHandleInformation
)
7037 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7041 HANDLE parent
= GetCurrentProcess ();
7042 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7044 if (DuplicateHandle (parent
,
7050 DUPLICATE_SAME_ACCESS
))
7052 /* It is possible that DuplicateHandle succeeds even
7053 though the socket wasn't really a kernel handle,
7054 because a real handle has the same value. So
7055 test whether the new handle really is a socket. */
7056 long nonblocking
= 0;
7057 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7059 pfn_closesocket (s
);
7064 CloseHandle (new_s
);
7069 eassert (fd
< MAXDESC
);
7070 fd_info
[fd
].hnd
= (HANDLE
) s
;
7072 /* set our own internal flags */
7073 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7079 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7081 /* attach child_process to fd_info */
7082 if (fd_info
[ fd
].cp
!= NULL
)
7084 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7088 fd_info
[ fd
].cp
= cp
;
7091 winsock_inuse
++; /* count open sockets */
7099 pfn_closesocket (s
);
7105 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7107 if (winsock_lib
== NULL
)
7110 return SOCKET_ERROR
;
7114 if (fd_info
[s
].flags
& FILE_SOCKET
)
7116 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7117 if (rc
== SOCKET_ERROR
)
7122 return SOCKET_ERROR
;
7126 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7128 if (winsock_lib
== NULL
)
7131 return SOCKET_ERROR
;
7135 if (fd_info
[s
].flags
& FILE_SOCKET
)
7137 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7138 if (rc
== SOCKET_ERROR
)
7143 return SOCKET_ERROR
;
7147 sys_htons (u_short hostshort
)
7149 return (winsock_lib
!= NULL
) ?
7150 pfn_htons (hostshort
) : hostshort
;
7154 sys_ntohs (u_short netshort
)
7156 return (winsock_lib
!= NULL
) ?
7157 pfn_ntohs (netshort
) : netshort
;
7161 sys_inet_addr (const char * cp
)
7163 return (winsock_lib
!= NULL
) ?
7164 pfn_inet_addr (cp
) : INADDR_NONE
;
7168 sys_gethostname (char * name
, int namelen
)
7170 if (winsock_lib
!= NULL
)
7175 retval
= pfn_gethostname (name
, namelen
);
7176 if (retval
== SOCKET_ERROR
)
7181 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7182 return !GetComputerName (name
, (DWORD
*)&namelen
);
7185 return SOCKET_ERROR
;
7189 sys_gethostbyname (const char * name
)
7191 struct hostent
* host
;
7192 int h_err
= h_errno
;
7194 if (winsock_lib
== NULL
)
7196 h_errno
= NO_RECOVERY
;
7202 host
= pfn_gethostbyname (name
);
7214 sys_getservbyname (const char * name
, const char * proto
)
7216 struct servent
* serv
;
7218 if (winsock_lib
== NULL
)
7225 serv
= pfn_getservbyname (name
, proto
);
7232 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7234 if (winsock_lib
== NULL
)
7237 return SOCKET_ERROR
;
7241 if (fd_info
[s
].flags
& FILE_SOCKET
)
7243 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7244 if (rc
== SOCKET_ERROR
)
7249 return SOCKET_ERROR
;
7253 sys_shutdown (int s
, int how
)
7255 if (winsock_lib
== NULL
)
7258 return SOCKET_ERROR
;
7262 if (fd_info
[s
].flags
& FILE_SOCKET
)
7264 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7265 if (rc
== SOCKET_ERROR
)
7270 return SOCKET_ERROR
;
7274 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7276 if (winsock_lib
== NULL
)
7279 return SOCKET_ERROR
;
7283 if (fd_info
[s
].flags
& FILE_SOCKET
)
7285 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7286 (const char *)optval
, optlen
);
7287 if (rc
== SOCKET_ERROR
)
7292 return SOCKET_ERROR
;
7296 sys_listen (int s
, int backlog
)
7298 if (winsock_lib
== NULL
)
7301 return SOCKET_ERROR
;
7305 if (fd_info
[s
].flags
& FILE_SOCKET
)
7307 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7308 if (rc
== SOCKET_ERROR
)
7311 fd_info
[s
].flags
|= FILE_LISTEN
;
7315 return SOCKET_ERROR
;
7319 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7321 if (winsock_lib
== NULL
)
7324 return SOCKET_ERROR
;
7328 if (fd_info
[s
].flags
& FILE_SOCKET
)
7330 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7331 if (rc
== SOCKET_ERROR
)
7336 return SOCKET_ERROR
;
7340 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7342 if (winsock_lib
== NULL
)
7349 if (fd_info
[s
].flags
& FILE_LISTEN
)
7351 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7353 if (t
== INVALID_SOCKET
)
7356 fd
= socket_to_fd (t
);
7360 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7361 ResetEvent (fd_info
[s
].cp
->char_avail
);
7370 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7371 struct sockaddr
* from
, int * fromlen
)
7373 if (winsock_lib
== NULL
)
7376 return SOCKET_ERROR
;
7380 if (fd_info
[s
].flags
& FILE_SOCKET
)
7382 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7383 if (rc
== SOCKET_ERROR
)
7388 return SOCKET_ERROR
;
7392 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7393 const struct sockaddr
* to
, int tolen
)
7395 if (winsock_lib
== NULL
)
7398 return SOCKET_ERROR
;
7402 if (fd_info
[s
].flags
& FILE_SOCKET
)
7404 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7405 if (rc
== SOCKET_ERROR
)
7410 return SOCKET_ERROR
;
7413 /* Windows does not have an fcntl function. Provide an implementation
7414 good enough for Emacs. */
7416 fcntl (int s
, int cmd
, int options
)
7418 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7419 invoked in a context where fd1 is closed and all descriptors less
7420 than fd1 are open, so sys_dup is an adequate implementation. */
7421 if (cmd
== F_DUPFD_CLOEXEC
)
7424 if (winsock_lib
== NULL
)
7431 if (fd_info
[s
].flags
& FILE_SOCKET
)
7433 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7435 unsigned long nblock
= 1;
7436 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7437 if (rc
== SOCKET_ERROR
)
7439 /* Keep track of the fact that we set this to non-blocking. */
7440 fd_info
[s
].flags
|= FILE_NDELAY
;
7446 return SOCKET_ERROR
;
7450 return SOCKET_ERROR
;
7454 /* Shadow main io functions: we need to handle pipes and sockets more
7455 intelligently, and implement non-blocking mode as well. */
7468 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7470 child_process
* cp
= fd_info
[fd
].cp
;
7472 fd_info
[fd
].cp
= NULL
;
7474 if (CHILD_ACTIVE (cp
))
7476 /* if last descriptor to active child_process then cleanup */
7478 for (i
= 0; i
< MAXDESC
; i
++)
7482 if (fd_info
[i
].cp
== cp
)
7487 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7489 if (winsock_lib
== NULL
) emacs_abort ();
7491 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7492 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7494 winsock_inuse
--; /* count open sockets */
7496 /* If the process handle is NULL, it's either a socket
7497 or serial connection, or a subprocess that was
7498 already reaped by reap_subprocess, but whose
7499 resources were not yet freed, because its output was
7500 not fully read yet by the time it was reaped. (This
7501 usually happens with async subprocesses whose output
7502 is being read by Emacs.) Otherwise, this process was
7503 not reaped yet, so we set its FD to a negative value
7504 to make sure sys_select will eventually get to
7505 calling the SIGCHLD handler for it, which will then
7506 invoke waitpid and reap_subprocess. */
7507 if (cp
->procinfo
.hProcess
== NULL
)
7515 if (fd
>= 0 && fd
< MAXDESC
)
7516 fd_info
[fd
].flags
= 0;
7518 /* Note that sockets do not need special treatment here (at least on
7519 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7520 closesocket is equivalent to CloseHandle, which is to be expected
7521 because socket handles are fully fledged kernel handles. */
7533 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7535 /* duplicate our internal info as well */
7536 fd_info
[new_fd
] = fd_info
[fd
];
7542 sys_dup2 (int src
, int dst
)
7546 if (dst
< 0 || dst
>= MAXDESC
)
7552 /* make sure we close the destination first if it's a pipe or socket */
7553 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7556 rc
= _dup2 (src
, dst
);
7559 /* duplicate our internal info as well */
7560 fd_info
[dst
] = fd_info
[src
];
7566 pipe2 (int * phandles
, int pipe2_flags
)
7571 eassert (pipe2_flags
== O_CLOEXEC
);
7573 /* make pipe handles non-inheritable; when we spawn a child, we
7574 replace the relevant handle with an inheritable one. Also put
7575 pipes into binary mode; we will do text mode translation ourselves
7577 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7581 /* Protect against overflow, since Windows can open more handles than
7582 our fd_info array has room for. */
7583 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7585 _close (phandles
[0]);
7586 _close (phandles
[1]);
7592 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7593 fd_info
[phandles
[0]].flags
= flags
;
7595 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7596 fd_info
[phandles
[1]].flags
= flags
;
7603 /* Function to do blocking read of one byte, needed to implement
7604 select. It is only allowed on communication ports, sockets, or
7607 _sys_read_ahead (int fd
)
7612 if (fd
< 0 || fd
>= MAXDESC
)
7613 return STATUS_READ_ERROR
;
7615 cp
= fd_info
[fd
].cp
;
7617 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7618 return STATUS_READ_ERROR
;
7620 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7621 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7623 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7627 cp
->status
= STATUS_READ_IN_PROGRESS
;
7629 if (fd_info
[fd
].flags
& FILE_PIPE
)
7631 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7633 /* Give subprocess time to buffer some more output for us before
7634 reporting that input is available; we need this because Windows 95
7635 connects DOS programs to pipes by making the pipe appear to be
7636 the normal console stdout - as a result most DOS programs will
7637 write to stdout without buffering, ie. one character at a
7638 time. Even some W32 programs do this - "dir" in a command
7639 shell on NT is very slow if we don't do this. */
7642 int wait
= w32_pipe_read_delay
;
7648 /* Yield remainder of our time slice, effectively giving a
7649 temporary priority boost to the child process. */
7653 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7655 HANDLE hnd
= fd_info
[fd
].hnd
;
7656 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7659 /* Configure timeouts for blocking read. */
7660 if (!GetCommTimeouts (hnd
, &ct
))
7662 cp
->status
= STATUS_READ_ERROR
;
7663 return STATUS_READ_ERROR
;
7665 ct
.ReadIntervalTimeout
= 0;
7666 ct
.ReadTotalTimeoutMultiplier
= 0;
7667 ct
.ReadTotalTimeoutConstant
= 0;
7668 if (!SetCommTimeouts (hnd
, &ct
))
7670 cp
->status
= STATUS_READ_ERROR
;
7671 return STATUS_READ_ERROR
;
7674 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7676 if (GetLastError () != ERROR_IO_PENDING
)
7678 cp
->status
= STATUS_READ_ERROR
;
7679 return STATUS_READ_ERROR
;
7681 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7683 cp
->status
= STATUS_READ_ERROR
;
7684 return STATUS_READ_ERROR
;
7688 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7690 unsigned long nblock
= 0;
7691 /* We always want this to block, so temporarily disable NDELAY. */
7692 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7693 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7695 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7697 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7700 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7704 if (rc
== sizeof (char))
7705 cp
->status
= STATUS_READ_SUCCEEDED
;
7707 cp
->status
= STATUS_READ_FAILED
;
7713 _sys_wait_accept (int fd
)
7719 if (fd
< 0 || fd
>= MAXDESC
)
7720 return STATUS_READ_ERROR
;
7722 cp
= fd_info
[fd
].cp
;
7724 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7725 return STATUS_READ_ERROR
;
7727 cp
->status
= STATUS_READ_FAILED
;
7729 hEv
= pfn_WSACreateEvent ();
7730 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7731 if (rc
!= SOCKET_ERROR
)
7734 rc
= WaitForSingleObject (hEv
, 500);
7736 } while (rc
== WAIT_TIMEOUT
7737 && cp
->status
!= STATUS_READ_ERROR
7739 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7740 if (rc
== WAIT_OBJECT_0
)
7741 cp
->status
= STATUS_READ_SUCCEEDED
;
7743 pfn_WSACloseEvent (hEv
);
7749 sys_read (int fd
, char * buffer
, unsigned int count
)
7754 char * orig_buffer
= buffer
;
7762 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7764 child_process
*cp
= fd_info
[fd
].cp
;
7766 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7774 /* re-read CR carried over from last read */
7775 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7777 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7781 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7784 /* presence of a child_process structure means we are operating in
7785 non-blocking mode - otherwise we just call _read directly.
7786 Note that the child_process structure might be missing because
7787 reap_subprocess has been called; in this case the pipe is
7788 already broken, so calling _read on it is okay. */
7791 int current_status
= cp
->status
;
7793 switch (current_status
)
7795 case STATUS_READ_FAILED
:
7796 case STATUS_READ_ERROR
:
7797 /* report normal EOF if nothing in buffer */
7799 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7802 case STATUS_READ_READY
:
7803 case STATUS_READ_IN_PROGRESS
:
7804 DebPrint (("sys_read called when read is in progress\n"));
7805 errno
= EWOULDBLOCK
;
7808 case STATUS_READ_SUCCEEDED
:
7809 /* consume read-ahead char */
7810 *buffer
++ = cp
->chr
;
7813 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7814 ResetEvent (cp
->char_avail
);
7816 case STATUS_READ_ACKNOWLEDGED
:
7820 DebPrint (("sys_read: bad status %d\n", current_status
));
7825 if (fd_info
[fd
].flags
& FILE_PIPE
)
7827 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7828 to_read
= min (waiting
, (DWORD
) count
);
7831 nchars
+= _read (fd
, buffer
, to_read
);
7833 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7835 HANDLE hnd
= fd_info
[fd
].hnd
;
7836 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7842 /* Configure timeouts for non-blocking read. */
7843 if (!GetCommTimeouts (hnd
, &ct
))
7848 ct
.ReadIntervalTimeout
= MAXDWORD
;
7849 ct
.ReadTotalTimeoutMultiplier
= 0;
7850 ct
.ReadTotalTimeoutConstant
= 0;
7851 if (!SetCommTimeouts (hnd
, &ct
))
7857 if (!ResetEvent (ovl
->hEvent
))
7862 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
7864 if (GetLastError () != ERROR_IO_PENDING
)
7869 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7878 else /* FILE_SOCKET */
7880 if (winsock_lib
== NULL
) emacs_abort ();
7882 /* do the equivalent of a non-blocking read */
7883 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
7884 if (waiting
== 0 && nchars
== 0)
7886 errno
= EWOULDBLOCK
;
7892 /* always use binary mode for sockets */
7893 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
7894 if (res
== SOCKET_ERROR
)
7896 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
7897 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
7907 int nread
= _read (fd
, buffer
, count
);
7910 else if (nchars
== 0)
7915 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7916 /* Perform text mode translation if required. */
7917 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7919 nchars
= crlf_to_lf (nchars
, orig_buffer
);
7920 /* If buffer contains only CR, return that. To be absolutely
7921 sure we should attempt to read the next char, but in
7922 practice a CR to be followed by LF would not appear by
7923 itself in the buffer. */
7924 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
7926 fd_info
[fd
].flags
|= FILE_LAST_CR
;
7932 nchars
= _read (fd
, buffer
, count
);
7937 /* From w32xfns.c */
7938 extern HANDLE interrupt_handle
;
7940 /* For now, don't bother with a non-blocking mode */
7942 sys_write (int fd
, const void * buffer
, unsigned int count
)
7952 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7954 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
7960 /* Perform text mode translation if required. */
7961 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7963 char * tmpbuf
= alloca (count
* 2);
7964 unsigned char * src
= (void *)buffer
;
7965 unsigned char * dst
= tmpbuf
;
7970 unsigned char *next
;
7971 /* copy next line or remaining bytes */
7972 next
= _memccpy (dst
, src
, '\n', nbytes
);
7975 /* copied one line ending with '\n' */
7976 int copied
= next
- dst
;
7979 /* insert '\r' before '\n' */
7986 /* copied remaining partial line -> now finished */
7993 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
7995 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
7996 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
7997 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8000 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8002 if (GetLastError () != ERROR_IO_PENDING
)
8007 if (detect_input_pending ())
8008 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8011 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8012 if (active
== WAIT_OBJECT_0
)
8013 { /* User pressed C-g, cancel write, then leave. Don't bother
8014 cleaning up as we may only get stuck in buggy drivers. */
8015 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8020 if (active
== WAIT_OBJECT_0
+ 1
8021 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8028 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8030 unsigned long nblock
= 0;
8031 if (winsock_lib
== NULL
) emacs_abort ();
8033 /* TODO: implement select() properly so non-blocking I/O works. */
8034 /* For now, make sure the write blocks. */
8035 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8036 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8038 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8040 /* Set the socket back to non-blocking if it was before,
8041 for other operations that support it. */
8042 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8045 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8048 if (nchars
== SOCKET_ERROR
)
8050 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8051 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8057 /* Some networked filesystems don't like too large writes, so
8058 break them into smaller chunks. See the Comments section of
8059 the MSDN documentation of WriteFile for details behind the
8060 choice of the value of CHUNK below. See also the thread
8061 http://thread.gmane.org/gmane.comp.version-control.git/145294
8062 in the git mailing list. */
8063 const unsigned char *p
= buffer
;
8064 const unsigned chunk
= 30 * 1024 * 1024;
8069 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8070 int n
= _write (fd
, p
, this_chunk
);
8078 else if (n
< this_chunk
)
8089 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8091 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8093 /* Return information about network interface IFNAME, or about all
8094 interfaces (if IFNAME is nil). */
8096 network_interface_get_info (Lisp_Object ifname
)
8098 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8099 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8100 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8101 Lisp_Object res
= Qnil
;
8103 if (retval
== ERROR_BUFFER_OVERFLOW
)
8105 ainfo
= xrealloc (ainfo
, ainfo_len
);
8106 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8109 if (retval
== ERROR_SUCCESS
)
8111 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8112 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8114 struct sockaddr_in sa
;
8116 /* For the below, we need some winsock functions, so make sure
8117 the winsock DLL is loaded. If we cannot successfully load
8118 it, they will have no use of the information we provide,
8120 if (!winsock_lib
&& !init_winsock (1))
8123 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8125 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8127 /* Present Unix-compatible interface names, instead of the
8128 Windows names, which are really GUIDs not readable by
8130 static const char *ifmt
[] = {
8131 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8146 switch (adapter
->Type
)
8148 case MIB_IF_TYPE_ETHERNET
:
8149 /* Windows before Vista reports wireless adapters as
8150 Ethernet. Work around by looking at the Description
8152 if (strstr (adapter
->Description
, "Wireless "))
8155 if_num
= wlan_count
++;
8159 ifmt_idx
= ETHERNET
;
8160 if_num
= eth_count
++;
8163 case MIB_IF_TYPE_TOKENRING
:
8164 ifmt_idx
= TOKENRING
;
8165 if_num
= tr_count
++;
8167 case MIB_IF_TYPE_FDDI
:
8169 if_num
= fddi_count
++;
8171 case MIB_IF_TYPE_PPP
:
8173 if_num
= ppp_count
++;
8175 case MIB_IF_TYPE_SLIP
:
8177 if_num
= sl_count
++;
8179 case IF_TYPE_IEEE80211
:
8181 if_num
= wlan_count
++;
8183 case MIB_IF_TYPE_LOOPBACK
:
8186 ifmt_idx
= LOOPBACK
;
8187 if_num
= lo_count
++;
8193 ifmt_idx
= OTHER_IF
;
8194 if_num
= ifx_count
++;
8197 if (ifmt_idx
== NONE
)
8199 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8201 sa
.sin_family
= AF_INET
;
8202 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8203 if (ip_addr
== INADDR_NONE
)
8205 /* Bogus address, skip this interface. */
8208 sa
.sin_addr
.s_addr
= ip_addr
;
8211 res
= Fcons (Fcons (build_string (namebuf
),
8212 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8213 sizeof (struct sockaddr
))),
8215 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8217 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8218 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8219 Lisp_Object flags
= Qnil
;
8223 /* Flags. We guess most of them by type, since the
8224 Windows flags are different and hard to get by. */
8225 flags
= Fcons (intern ("up"), flags
);
8226 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8228 flags
= Fcons (intern ("broadcast"), flags
);
8229 flags
= Fcons (intern ("multicast"), flags
);
8231 flags
= Fcons (intern ("running"), flags
);
8232 if (ifmt_idx
== PPP
)
8234 flags
= Fcons (intern ("pointopoint"), flags
);
8235 flags
= Fcons (intern ("noarp"), flags
);
8237 if (adapter
->HaveWins
)
8238 flags
= Fcons (intern ("WINS"), flags
);
8239 if (adapter
->DhcpEnabled
)
8240 flags
= Fcons (intern ("dynamic"), flags
);
8242 res
= Fcons (flags
, res
);
8244 /* Hardware address and its family. */
8245 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8246 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8247 /* Windows does not support AF_LINK or AF_PACKET family
8248 of addresses. Use an arbitrary family number that is
8249 identical to what GNU/Linux returns. */
8250 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8253 sa
.sin_family
= AF_INET
;
8254 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8255 if (net_mask
!= INADDR_NONE
)
8257 sa
.sin_addr
.s_addr
= net_mask
;
8259 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8260 sizeof (struct sockaddr
)),
8264 res
= Fcons (Qnil
, res
);
8266 sa
.sin_family
= AF_INET
;
8267 if (ip_addr
!= INADDR_NONE
)
8269 /* Broadcast address is only reported by
8270 GetAdaptersAddresses, which is of limited
8271 availability. Generate it on our own. */
8272 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8274 sa
.sin_addr
.s_addr
= bcast_addr
;
8276 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8277 sizeof (struct sockaddr
)),
8281 sa
.sin_addr
.s_addr
= ip_addr
;
8283 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8284 sizeof (struct sockaddr
)),
8288 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8291 /* GetAdaptersInfo is documented to not report loopback
8292 interfaces, so we generate one out of thin air. */
8295 sa
.sin_family
= AF_INET
;
8299 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8300 res
= Fcons (Fcons (build_string ("lo"),
8301 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8302 sizeof (struct sockaddr
))),
8305 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8307 res
= Fcons (Fcons (intern ("running"),
8308 Fcons (intern ("loopback"),
8309 Fcons (intern ("up"), Qnil
))), Qnil
);
8310 /* 772 is what 3 different GNU/Linux systems report for
8311 the loopback interface. */
8312 res
= Fcons (Fcons (make_number (772),
8313 Fmake_vector (make_number (6),
8316 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8317 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8318 sizeof (struct sockaddr
)),
8320 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8321 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8322 sizeof (struct sockaddr
)),
8324 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8325 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8326 sizeof (struct sockaddr
)),
8339 network_interface_list (void)
8341 return network_interface_get_info (Qnil
);
8345 network_interface_info (Lisp_Object ifname
)
8347 return network_interface_get_info (ifname
);
8351 /* The Windows CRT functions are "optimized for speed", so they don't
8352 check for timezone and DST changes if they were last called less
8353 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8354 all Emacs features that repeatedly call time functions (e.g.,
8355 display-time) are in real danger of missing timezone and DST
8356 changes. Calling tzset before each localtime call fixes that. */
8358 sys_localtime (const time_t *t
)
8361 return localtime (t
);
8366 /* Try loading LIBRARY_ID from the file(s) specified in
8367 Vdynamic_library_alist. If the library is loaded successfully,
8368 return the handle of the DLL, and record the filename in the
8369 property :loaded-from of LIBRARY_ID. If the library could not be
8370 found, or when it was already loaded (because the handle is not
8371 recorded anywhere, and so is lost after use), return NULL.
8373 We could also save the handle in :loaded-from, but currently
8374 there's no use case for it. */
8376 w32_delayed_load (Lisp_Object library_id
)
8378 HMODULE dll_handle
= NULL
;
8380 CHECK_SYMBOL (library_id
);
8382 if (CONSP (Vdynamic_library_alist
)
8383 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8385 Lisp_Object found
= Qnil
;
8386 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8389 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8391 Lisp_Object dll
= XCAR (dlls
);
8392 char name
[MAX_UTF8_PATH
];
8396 dll
= ENCODE_FILE (dll
);
8397 if (w32_unicode_filenames
)
8399 wchar_t name_w
[MAX_PATH
];
8401 filename_to_utf16 (SSDATA (dll
), name_w
);
8402 dll_handle
= LoadLibraryW (name_w
);
8405 res
= GetModuleFileNameW (dll_handle
, name_w
,
8408 filename_from_utf16 (name_w
, name
);
8413 char name_a
[MAX_PATH
];
8415 filename_to_ansi (SSDATA (dll
), name_a
);
8416 dll_handle
= LoadLibraryA (name_a
);
8419 res
= GetModuleFileNameA (dll_handle
, name_a
,
8422 filename_from_ansi (name_a
, name
);
8427 ptrdiff_t len
= strlen (name
);
8430 /* Possibly truncated */
8431 ? make_specified_string (name
, -1, len
, 1)
8437 Fput (library_id
, QCloaded_from
, found
);
8445 check_windows_init_file (void)
8447 /* A common indication that Emacs is not installed properly is when
8448 it cannot find the Windows installation file. If this file does
8449 not exist in the expected place, tell the user. */
8451 if (!noninteractive
&& !inhibit_window_system
8452 /* Vload_path is not yet initialized when we are loading
8454 && NILP (Vpurify_flag
))
8456 Lisp_Object init_file
;
8459 /* Implementation note: this function runs early during Emacs
8460 startup, before startup.el is run. So Vload_path is still in
8461 its initial unibyte form, but it holds UTF-8 encoded file
8462 names, since init_callproc was already called. So we do not
8463 need to ENCODE_FILE here, but we do need to convert the file
8464 names from UTF-8 to ANSI. */
8465 init_file
= build_string ("term/w32-win");
8466 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
8469 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8470 char *init_file_name
= SDATA (init_file
);
8471 char *load_path
= SDATA (load_path_print
);
8472 char *buffer
= alloca (1024
8473 + strlen (init_file_name
)
8474 + strlen (load_path
));
8479 "The Emacs Windows initialization file \"%s.el\" "
8480 "could not be found in your Emacs installation. "
8481 "Emacs checked the following directories for this file:\n"
8483 "When Emacs cannot find this file, it usually means that it "
8484 "was not installed properly, or its distribution file was "
8485 "not unpacked properly.\nSee the README.W32 file in the "
8486 "top-level Emacs directory for more information.",
8487 init_file_name
, load_path
);
8488 needed
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8492 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8494 MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8496 needed
= WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8497 NULL
, 0, NULL
, NULL
);
8500 char *msg_a
= alloca (needed
+ 1);
8502 WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8509 "Emacs Abort Dialog",
8510 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8511 /* Use the low-level system abort. */
8522 term_ntproc (int ignored
)
8528 /* shutdown the socket interface if necessary */
8535 init_ntproc (int dumping
)
8537 sigset_t initial_mask
= 0;
8539 /* Initialize the socket interface now if available and requested by
8540 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8541 delayed until open-network-stream is called (w32-has-winsock can
8542 also be used to dynamically load or reload winsock).
8544 Conveniently, init_environment is called before us, so
8545 PRELOAD_WINSOCK can be set in the registry. */
8547 /* Always initialize this correctly. */
8550 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8551 init_winsock (TRUE
);
8553 /* Initial preparation for subprocess support: replace our standard
8554 handles with non-inheritable versions. */
8557 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8558 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8559 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8561 parent
= GetCurrentProcess ();
8563 /* ignore errors when duplicating and closing; typically the
8564 handles will be invalid when running as a gui program. */
8565 DuplicateHandle (parent
,
8566 GetStdHandle (STD_INPUT_HANDLE
),
8571 DUPLICATE_SAME_ACCESS
);
8573 DuplicateHandle (parent
,
8574 GetStdHandle (STD_OUTPUT_HANDLE
),
8579 DUPLICATE_SAME_ACCESS
);
8581 DuplicateHandle (parent
,
8582 GetStdHandle (STD_ERROR_HANDLE
),
8587 DUPLICATE_SAME_ACCESS
);
8593 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8594 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8596 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8599 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8600 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8602 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8605 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8606 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8608 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8612 /* unfortunately, atexit depends on implementation of malloc */
8613 /* atexit (term_ntproc); */
8616 /* Make sure we start with all signals unblocked. */
8617 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8618 signal (SIGABRT
, term_ntproc
);
8622 /* determine which drives are fixed, for GetCachedVolumeInformation */
8624 /* GetDriveType must have trailing backslash. */
8625 char drive
[] = "A:\\";
8627 /* Loop over all possible drive letters */
8628 while (*drive
<= 'Z')
8630 /* Record if this drive letter refers to a fixed drive. */
8631 fixed_drives
[DRIVE_INDEX (*drive
)] =
8632 (GetDriveType (drive
) == DRIVE_FIXED
);
8637 /* Reset the volume info cache. */
8638 volume_cache
= NULL
;
8643 shutdown_handler ensures that buffers' autosave files are
8644 up to date when the user logs off, or the system shuts down.
8647 shutdown_handler (DWORD type
)
8649 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8650 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8651 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8652 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8654 /* Shut down cleanly, making sure autosave files are up to date. */
8655 shut_down_emacs (0, Qnil
);
8658 /* Allow other handlers to handle this signal. */
8663 globals_of_w32 is used to initialize those global variables that
8664 must always be initialized on startup even when the global variable
8665 initialized is non zero (see the function main in emacs.c).
8668 globals_of_w32 (void)
8670 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8672 get_process_times_fn
= (GetProcessTimes_Proc
)
8673 GetProcAddress (kernel32
, "GetProcessTimes");
8675 DEFSYM (QCloaded_from
, ":loaded-from");
8677 g_b_init_is_windows_9x
= 0;
8678 g_b_init_open_process_token
= 0;
8679 g_b_init_get_token_information
= 0;
8680 g_b_init_lookup_account_sid
= 0;
8681 g_b_init_get_sid_sub_authority
= 0;
8682 g_b_init_get_sid_sub_authority_count
= 0;
8683 g_b_init_get_security_info
= 0;
8684 g_b_init_get_file_security_w
= 0;
8685 g_b_init_get_file_security_a
= 0;
8686 g_b_init_get_security_descriptor_owner
= 0;
8687 g_b_init_get_security_descriptor_group
= 0;
8688 g_b_init_is_valid_sid
= 0;
8689 g_b_init_create_toolhelp32_snapshot
= 0;
8690 g_b_init_process32_first
= 0;
8691 g_b_init_process32_next
= 0;
8692 g_b_init_open_thread_token
= 0;
8693 g_b_init_impersonate_self
= 0;
8694 g_b_init_revert_to_self
= 0;
8695 g_b_init_get_process_memory_info
= 0;
8696 g_b_init_get_process_working_set_size
= 0;
8697 g_b_init_global_memory_status
= 0;
8698 g_b_init_global_memory_status_ex
= 0;
8699 g_b_init_equal_sid
= 0;
8700 g_b_init_copy_sid
= 0;
8701 g_b_init_get_length_sid
= 0;
8702 g_b_init_get_native_system_info
= 0;
8703 g_b_init_get_system_times
= 0;
8704 g_b_init_create_symbolic_link_w
= 0;
8705 g_b_init_create_symbolic_link_a
= 0;
8706 g_b_init_get_security_descriptor_dacl
= 0;
8707 g_b_init_convert_sd_to_sddl
= 0;
8708 g_b_init_convert_sddl_to_sd
= 0;
8709 g_b_init_is_valid_security_descriptor
= 0;
8710 g_b_init_set_file_security_w
= 0;
8711 g_b_init_set_file_security_a
= 0;
8712 g_b_init_get_adapters_info
= 0;
8713 num_of_processors
= 0;
8714 /* The following sets a handler for shutdown notifications for
8715 console apps. This actually applies to Emacs in both console and
8716 GUI modes, since we had to fool windows into thinking emacs is a
8717 console application to get console mode to work. */
8718 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8720 /* "None" is the default group name on standalone workstations. */
8721 strcpy (dflt_group_name
, "None");
8723 /* Reset, in case it has some value inherited from dump time. */
8724 w32_stat_get_owner_group
= 0;
8726 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8727 (a.k.a. "wide") APIs to invoke functions that accept file
8729 if (is_windows_9x ())
8730 w32_unicode_filenames
= 0;
8732 w32_unicode_filenames
= 1;
8735 /* For make-serial-process */
8737 serial_open (Lisp_Object port_obj
)
8739 char *port
= SSDATA (port_obj
);
8744 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8745 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8746 if (hnd
== INVALID_HANDLE_VALUE
)
8747 error ("Could not open %s", port
);
8748 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8750 error ("Could not open %s", port
);
8754 error ("Could not create child process");
8756 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8757 fd_info
[ fd
].hnd
= hnd
;
8758 fd_info
[ fd
].flags
|=
8759 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8760 if (fd_info
[ fd
].cp
!= NULL
)
8762 error ("fd_info[fd = %d] is already in use", fd
);
8764 fd_info
[ fd
].cp
= cp
;
8765 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8766 if (cp
->ovl_read
.hEvent
== NULL
)
8767 error ("Could not create read event");
8768 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8769 if (cp
->ovl_write
.hEvent
== NULL
)
8770 error ("Could not create write event");
8775 /* For serial-process-configure */
8777 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8779 Lisp_Object childp2
= Qnil
;
8780 Lisp_Object tem
= Qnil
;
8784 char summary
[4] = "???"; /* This usually becomes "8N1". */
8786 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8787 error ("Not a serial process");
8788 hnd
= fd_info
[ p
->outfd
].hnd
;
8790 childp2
= Fcopy_sequence (p
->childp
);
8792 /* Initialize timeouts for blocking read and blocking write. */
8793 if (!GetCommTimeouts (hnd
, &ct
))
8794 error ("GetCommTimeouts() failed");
8795 ct
.ReadIntervalTimeout
= 0;
8796 ct
.ReadTotalTimeoutMultiplier
= 0;
8797 ct
.ReadTotalTimeoutConstant
= 0;
8798 ct
.WriteTotalTimeoutMultiplier
= 0;
8799 ct
.WriteTotalTimeoutConstant
= 0;
8800 if (!SetCommTimeouts (hnd
, &ct
))
8801 error ("SetCommTimeouts() failed");
8802 /* Read port attributes and prepare default configuration. */
8803 memset (&dcb
, 0, sizeof (dcb
));
8804 dcb
.DCBlength
= sizeof (DCB
);
8805 if (!GetCommState (hnd
, &dcb
))
8806 error ("GetCommState() failed");
8809 dcb
.fAbortOnError
= FALSE
;
8810 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8815 /* Configure speed. */
8816 if (!NILP (Fplist_member (contact
, QCspeed
)))
8817 tem
= Fplist_get (contact
, QCspeed
);
8819 tem
= Fplist_get (p
->childp
, QCspeed
);
8821 dcb
.BaudRate
= XINT (tem
);
8822 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8824 /* Configure bytesize. */
8825 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8826 tem
= Fplist_get (contact
, QCbytesize
);
8828 tem
= Fplist_get (p
->childp
, QCbytesize
);
8830 tem
= make_number (8);
8832 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8833 error (":bytesize must be nil (8), 7, or 8");
8834 dcb
.ByteSize
= XINT (tem
);
8835 summary
[0] = XINT (tem
) + '0';
8836 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8838 /* Configure parity. */
8839 if (!NILP (Fplist_member (contact
, QCparity
)))
8840 tem
= Fplist_get (contact
, QCparity
);
8842 tem
= Fplist_get (p
->childp
, QCparity
);
8843 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8844 error (":parity must be nil (no parity), `even', or `odd'");
8845 dcb
.fParity
= FALSE
;
8846 dcb
.Parity
= NOPARITY
;
8847 dcb
.fErrorChar
= FALSE
;
8852 else if (EQ (tem
, Qeven
))
8856 dcb
.Parity
= EVENPARITY
;
8857 dcb
.fErrorChar
= TRUE
;
8859 else if (EQ (tem
, Qodd
))
8863 dcb
.Parity
= ODDPARITY
;
8864 dcb
.fErrorChar
= TRUE
;
8866 childp2
= Fplist_put (childp2
, QCparity
, tem
);
8868 /* Configure stopbits. */
8869 if (!NILP (Fplist_member (contact
, QCstopbits
)))
8870 tem
= Fplist_get (contact
, QCstopbits
);
8872 tem
= Fplist_get (p
->childp
, QCstopbits
);
8874 tem
= make_number (1);
8876 if (XINT (tem
) != 1 && XINT (tem
) != 2)
8877 error (":stopbits must be nil (1 stopbit), 1, or 2");
8878 summary
[2] = XINT (tem
) + '0';
8879 if (XINT (tem
) == 1)
8880 dcb
.StopBits
= ONESTOPBIT
;
8881 else if (XINT (tem
) == 2)
8882 dcb
.StopBits
= TWOSTOPBITS
;
8883 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
8885 /* Configure flowcontrol. */
8886 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
8887 tem
= Fplist_get (contact
, QCflowcontrol
);
8889 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
8890 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
8891 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
8892 dcb
.fOutxCtsFlow
= FALSE
;
8893 dcb
.fOutxDsrFlow
= FALSE
;
8894 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
8895 dcb
.fDsrSensitivity
= FALSE
;
8896 dcb
.fTXContinueOnXoff
= FALSE
;
8899 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
8900 dcb
.XonChar
= 17; /* Control-Q */
8901 dcb
.XoffChar
= 19; /* Control-S */
8904 /* Already configured. */
8906 else if (EQ (tem
, Qhw
))
8908 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
8909 dcb
.fOutxCtsFlow
= TRUE
;
8911 else if (EQ (tem
, Qsw
))
8916 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
8918 /* Activate configuration. */
8919 if (!SetCommState (hnd
, &dcb
))
8920 error ("SetCommState() failed");
8922 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
8923 pset_childp (p
, childp2
);
8929 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
8933 struct timespec timeout
;
8934 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8935 int fd
= process
->infd
;
8937 n
= sys_read (fd
, (char*)buf
, sz
);
8944 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8945 if (err
== EWOULDBLOCK
)
8948 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
8954 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
8956 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8957 int fd
= process
->outfd
;
8958 ssize_t n
= sys_write (fd
, buf
, sz
);
8960 /* 0 or more bytes written means everything went fine. */
8964 /* Negative bytes written means we got an error in errno.
8965 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8966 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
8967 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
8971 #endif /* HAVE_GNUTLS */