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
, "?"))
2158 /* Find the basename of fname_ansi. */
2159 char *p
= strrchr (fname_ansi
, '\\');
2165 cstatus
= filename_from_ansi (p
, fname_utf8
);
2169 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2170 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2171 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2175 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2176 memcpy (buf
, fname_utf8
, len
+ 1);
2180 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2181 FindClose (dir_handle
);
2186 /* Get long name for file, if possible (assumed to be absolute). */
2188 w32_get_long_filename (char * name
, char * buf
, int size
)
2193 char full
[ MAX_UTF8_PATH
];
2196 len
= strlen (name
);
2197 if (len
>= MAX_UTF8_PATH
)
2200 /* Use local copy for destructive modification. */
2201 memcpy (full
, name
, len
+1);
2202 unixtodos_filename (full
);
2204 /* Copy root part verbatim. */
2205 len
= parse_root (full
, (const char **)&p
);
2206 memcpy (o
, full
, len
);
2211 while (p
!= NULL
&& *p
)
2214 p
= strchr (q
, '\\');
2216 len
= get_long_basename (full
, o
, size
);
2239 w32_get_short_filename (char * name
, char * buf
, int size
)
2241 if (w32_unicode_filenames
)
2243 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2244 unsigned int retval
;
2246 filename_to_utf16 (name
, name_utf16
);
2247 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2248 if (retval
&& retval
< size
)
2249 filename_from_utf16 (short_name
, buf
);
2254 char name_ansi
[MAX_PATH
];
2256 filename_to_ansi (name
, name_ansi
);
2257 return GetShortPathNameA (name_ansi
, buf
, size
);
2261 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2262 MS-Windows ANSI codepage. If FILENAME includes characters not
2263 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2264 if it exists. This is needed because the w32 build wants to
2265 support file names outside of the system locale, but image
2266 libraries typically don't support wide (a.k.a. "Unicode") APIs
2267 required for that. */
2270 ansi_encode_filename (Lisp_Object filename
)
2272 Lisp_Object encoded_filename
;
2273 char fname
[MAX_PATH
];
2275 filename_to_ansi (SSDATA (filename
), fname
);
2276 if (_mbspbrk (fname
, "?"))
2278 char shortname
[MAX_PATH
];
2280 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2282 dostounix_filename (shortname
);
2283 encoded_filename
= build_string (shortname
);
2287 encoded_filename
= build_unibyte_string (fname
);
2288 return encoded_filename
;
2292 is_unc_volume (const char *filename
)
2294 const char *ptr
= filename
;
2296 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2299 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2305 /* Emulate the Posix unsetenv. */
2307 unsetenv (const char *name
)
2313 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2318 name_len
= strlen (name
);
2319 /* MS docs says an environment variable cannot be longer than 32K. */
2320 if (name_len
> 32767)
2325 /* It is safe to use 'alloca' with 32K size, since the stack is at
2326 least 2MB, and we set it to 8MB in the link command line. */
2327 var
= alloca (name_len
+ 2);
2328 strncpy (var
, name
, name_len
);
2329 var
[name_len
++] = '=';
2330 var
[name_len
] = '\0';
2331 return _putenv (var
);
2334 /* MS _putenv doesn't support removing a variable when the argument
2335 does not include the '=' character, so we fix that here. */
2337 sys_putenv (char *str
)
2339 const char *const name_end
= strchr (str
, '=');
2341 if (name_end
== NULL
)
2343 /* Remove the variable from the environment. */
2344 return unsetenv (str
);
2347 return _putenv (str
);
2350 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2353 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2356 HKEY hrootkey
= NULL
;
2359 /* Check both the current user and the local machine to see if
2360 we have any resources. */
2362 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2366 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2367 && (lpvalue
= xmalloc (cbData
)) != NULL
2368 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2370 RegCloseKey (hrootkey
);
2376 RegCloseKey (hrootkey
);
2379 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2383 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2384 && (lpvalue
= xmalloc (cbData
)) != NULL
2385 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2387 RegCloseKey (hrootkey
);
2393 RegCloseKey (hrootkey
);
2399 /* The argv[] array holds ANSI-encoded strings, and so this function
2400 works with ANS_encoded strings. */
2402 init_environment (char ** argv
)
2404 static const char * const tempdirs
[] = {
2405 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2410 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2412 /* Implementation note: This function explicitly works with ANSI
2413 file names, not with UTF-8 encoded file names. This is because
2414 this function pushes variables into the Emacs's environment, and
2415 the environment variables are always assumed to be in the
2416 locale-specific encoding. Do NOT call any functions that accept
2417 UTF-8 file names from this function! */
2419 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2420 temporary files and assume "/tmp" if $TMPDIR is unset, which
2421 will break on DOS/Windows. Refuse to work if we cannot find
2422 a directory, not even "c:/", usable for that purpose. */
2423 for (i
= 0; i
< imax
; i
++)
2425 const char *tmp
= tempdirs
[i
];
2428 tmp
= getenv (tmp
+ 1);
2429 /* Note that `access' can lie to us if the directory resides on a
2430 read-only filesystem, like CD-ROM or a write-protected floppy.
2431 The only way to be really sure is to actually create a file and
2432 see if it succeeds. But I think that's too much to ask. */
2434 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2435 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2437 char * var
= alloca (strlen (tmp
) + 8);
2438 sprintf (var
, "TMPDIR=%s", tmp
);
2439 _putenv (strdup (var
));
2446 Fcons (build_string ("no usable temporary directories found!!"),
2448 "While setting TMPDIR: ");
2450 /* Check for environment variables and use registry settings if they
2451 don't exist. Fallback on default values where applicable. */
2456 char locale_name
[32];
2457 char default_home
[MAX_PATH
];
2460 static const struct env_entry
2466 /* If the default value is NULL, we will use the value from the
2467 outside environment or the Registry, but will not push the
2468 variable into the Emacs environment if it is defined neither
2469 in the Registry nor in the outside environment. */
2471 {"PRELOAD_WINSOCK", NULL
},
2472 {"emacs_dir", "C:/emacs"},
2473 {"EMACSLOADPATH", NULL
},
2474 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2475 {"EMACSDATA", NULL
},
2476 {"EMACSPATH", NULL
},
2483 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2485 /* We need to copy dflt_envvars[] and work on the copy because we
2486 don't want the dumped Emacs to inherit the values of
2487 environment variables we saw during dumping (which could be on
2488 a different system). The defaults above must be left intact. */
2489 struct env_entry env_vars
[N_ENV_VARS
];
2491 for (i
= 0; i
< N_ENV_VARS
; i
++)
2492 env_vars
[i
] = dflt_envvars
[i
];
2494 /* For backwards compatibility, check if a .emacs file exists in C:/
2495 If not, then we can try to default to the appdata directory under the
2496 user's profile, which is more likely to be writable. */
2497 if (sys_access ("C:/.emacs", F_OK
) != 0)
2499 HRESULT profile_result
;
2500 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2501 of Windows 95 and NT4 that have not been updated to include
2503 ShGetFolderPath_fn get_folder_path
;
2504 get_folder_path
= (ShGetFolderPath_fn
)
2505 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2507 if (get_folder_path
!= NULL
)
2509 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2512 /* If we can't get the appdata dir, revert to old behavior. */
2513 if (profile_result
== S_OK
)
2515 env_vars
[0].def_value
= default_home
;
2521 /* Get default locale info and use it for LANG. */
2522 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2523 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2524 locale_name
, sizeof (locale_name
)))
2526 for (i
= 0; i
< N_ENV_VARS
; i
++)
2528 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2530 env_vars
[i
].def_value
= locale_name
;
2536 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2538 /* Treat emacs_dir specially: set it unconditionally based on our
2542 char modname
[MAX_PATH
];
2544 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2546 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2550 if ((p
= _mbsrchr (modname
, '\\'))
2551 /* From bin means installed Emacs, from src means uninstalled. */
2552 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2554 char buf
[SET_ENV_BUF_SIZE
];
2555 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2558 for (p
= modname
; *p
; p
= CharNext (p
))
2559 if (*p
== '\\') *p
= '/';
2561 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2562 _putenv (strdup (buf
));
2563 /* If we are running from the Posix-like build tree, define
2564 SHELL to point to our own cmdproxy. The loop below will
2565 then disregard PATH_EXEC and the default value. */
2566 if (within_build_tree
)
2568 _snprintf (buf
, sizeof (buf
) - 1,
2569 "SHELL=%s/nt/cmdproxy.exe", modname
);
2570 _putenv (strdup (buf
));
2575 for (i
= 0; i
< N_ENV_VARS
; i
++)
2577 if (!getenv (env_vars
[i
].name
))
2580 char bufc
[SET_ENV_BUF_SIZE
];
2582 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2583 /* Also ignore empty environment variables. */
2588 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2590 /* Look for cmdproxy.exe in every directory in
2591 PATH_EXEC. FIXME: This does not find cmdproxy
2592 in nt/ when we run uninstalled. */
2593 char fname
[MAX_PATH
];
2594 const char *pstart
= PATH_EXEC
, *pend
;
2597 pend
= _mbschr (pstart
, ';');
2599 pend
= pstart
+ strlen (pstart
);
2600 /* Be defensive against series of ;;; characters. */
2603 strncpy (fname
, pstart
, pend
- pstart
);
2604 fname
[pend
- pstart
] = '/';
2605 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2606 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2608 if (sys_access (bufc
, F_OK
) == 0)
2621 /* If not found in any directory, use the
2622 default as the last resort. */
2623 lpval
= env_vars
[i
].def_value
;
2624 dwType
= REG_EXPAND_SZ
;
2630 lpval
= env_vars
[i
].def_value
;
2631 dwType
= REG_EXPAND_SZ
;
2633 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2634 Vdelayed_warnings_list
2635 = Fcons (listn (CONSTYPE_HEAP
, 2,
2636 intern ("initialization"),
2637 build_string ("Setting HOME to C:\\ by default is deprecated")),
2638 Vdelayed_warnings_list
);
2643 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2645 if (dwType
== REG_EXPAND_SZ
)
2646 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2647 else if (dwType
== REG_SZ
)
2648 strcpy (buf1
, lpval
);
2649 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2651 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2653 _putenv (strdup (buf2
));
2663 /* Rebuild system configuration to reflect invoking system. */
2664 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2666 /* Another special case: on NT, the PATH variable is actually named
2667 "Path" although cmd.exe (perhaps NT itself) arranges for
2668 environment variable lookup and setting to be case insensitive.
2669 However, Emacs assumes a fully case sensitive environment, so we
2670 need to change "Path" to "PATH" to match the expectations of
2671 various elisp packages. We do this by the sneaky method of
2672 modifying the string in the C runtime environ entry.
2674 The same applies to COMSPEC. */
2678 for (envp
= environ
; *envp
; envp
++)
2679 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2680 memcpy (*envp
, "PATH=", 5);
2681 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2682 memcpy (*envp
, "COMSPEC=", 8);
2685 /* Remember the initial working directory for getcwd. */
2686 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2687 Does it matter anywhere in Emacs? */
2688 if (w32_unicode_filenames
)
2690 wchar_t wstartup_dir
[MAX_PATH
];
2692 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2694 filename_from_utf16 (wstartup_dir
, startup_dir
);
2698 char astartup_dir
[MAX_PATH
];
2700 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2702 filename_from_ansi (astartup_dir
, startup_dir
);
2706 static char modname
[MAX_PATH
];
2708 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2713 /* Determine if there is a middle mouse button, to allow parse_button
2714 to decide whether right mouse events should be mouse-2 or
2716 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2721 /* Called from expand-file-name when default-directory is not a string. */
2724 emacs_root_dir (void)
2726 static char root_dir
[MAX_UTF8_PATH
];
2729 p
= getenv ("emacs_dir");
2732 filename_from_ansi (p
, root_dir
);
2733 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2734 dostounix_filename (root_dir
);
2738 #include <sys/timeb.h>
2740 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2742 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2747 tv
->tv_sec
= tb
.time
;
2748 tv
->tv_usec
= tb
.millitm
* 1000L;
2749 /* Implementation note: _ftime sometimes doesn't update the dstflag
2750 according to the new timezone when the system timezone is
2751 changed. We could fix that by using GetSystemTime and
2752 GetTimeZoneInformation, but that doesn't seem necessary, since
2753 Emacs always calls gettimeofday with the 2nd argument NULL (see
2754 current_emacs_time). */
2757 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2758 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2763 /* Emulate fdutimens. */
2765 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2766 TIMESPEC[0] and TIMESPEC[1], respectively.
2767 FD must be either negative -- in which case it is ignored --
2768 or a file descriptor that is open on FILE.
2769 If FD is nonnegative, then FILE can be NULL, which means
2770 use just futimes instead of utimes.
2771 If TIMESPEC is null, FAIL.
2772 Return 0 on success, -1 (setting errno) on failure. */
2775 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2782 if (fd
< 0 && !file
)
2787 /* _futime's prototype defines 2nd arg as having the type 'struct
2788 _utimbuf', while utime needs to accept 'struct utimbuf' for
2789 compatibility with Posix. So we need to use 2 different (but
2790 equivalent) types to avoid compiler warnings, sigh. */
2793 struct _utimbuf _ut
;
2795 _ut
.actime
= timespec
[0].tv_sec
;
2796 _ut
.modtime
= timespec
[1].tv_sec
;
2797 return _futime (fd
, &_ut
);
2803 ut
.actime
= timespec
[0].tv_sec
;
2804 ut
.modtime
= timespec
[1].tv_sec
;
2805 /* Call 'utime', which is implemented below, not the MS library
2806 function, which fails on directories. */
2807 return utime (file
, &ut
);
2812 /* ------------------------------------------------------------------------- */
2813 /* IO support and wrapper functions for the Windows API. */
2814 /* ------------------------------------------------------------------------- */
2816 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2817 on network directories, so we handle that case here.
2818 (Ulrich Leodolter, 1/11/95). */
2820 sys_ctime (const time_t *t
)
2822 char *str
= (char *) ctime (t
);
2823 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2826 /* Emulate sleep...we could have done this with a define, but that
2827 would necessitate including windows.h in the files that used it.
2828 This is much easier. */
2830 sys_sleep (int seconds
)
2832 Sleep (seconds
* 1000);
2835 /* Internal MSVC functions for low-level descriptor munging */
2836 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2837 extern int __cdecl
_free_osfhnd (int fd
);
2839 /* parallel array of private info on file handles */
2840 filedesc fd_info
[ MAXDESC
];
2842 typedef struct volume_info_data
{
2843 struct volume_info_data
* next
;
2845 /* time when info was obtained */
2848 /* actual volume info */
2857 /* Global referenced by various functions. */
2858 static volume_info_data volume_info
;
2860 /* Vector to indicate which drives are local and fixed (for which cached
2861 data never expires). */
2862 static BOOL fixed_drives
[26];
2864 /* Consider cached volume information to be stale if older than 10s,
2865 at least for non-local drives. Info for fixed drives is never stale. */
2866 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2867 #define VOLINFO_STILL_VALID( root_dir, info ) \
2868 ( ( isalpha (root_dir[0]) && \
2869 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2870 || GetTickCount () - info->timestamp < 10000 )
2872 /* Cache support functions. */
2874 /* Simple linked list with linear search is sufficient. */
2875 static volume_info_data
*volume_cache
= NULL
;
2877 static volume_info_data
*
2878 lookup_volume_info (char * root_dir
)
2880 volume_info_data
* info
;
2882 for (info
= volume_cache
; info
; info
= info
->next
)
2883 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2889 add_volume_info (char * root_dir
, volume_info_data
* info
)
2891 info
->root_dir
= xstrdup (root_dir
);
2892 unixtodos_filename (info
->root_dir
);
2893 info
->next
= volume_cache
;
2894 volume_cache
= info
;
2898 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2899 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2900 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2901 static volume_info_data
*
2902 GetCachedVolumeInformation (char * root_dir
)
2904 volume_info_data
* info
;
2905 char default_root
[ MAX_UTF8_PATH
];
2906 char name
[MAX_PATH
+1];
2907 char type
[MAX_PATH
+1];
2909 /* NULL for root_dir means use root from current directory. */
2910 if (root_dir
== NULL
)
2912 if (w32_unicode_filenames
)
2914 wchar_t curdirw
[MAX_PATH
];
2916 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
2918 filename_from_utf16 (curdirw
, default_root
);
2922 char curdira
[MAX_PATH
];
2924 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
2926 filename_from_ansi (curdira
, default_root
);
2928 parse_root (default_root
, (const char **)&root_dir
);
2930 root_dir
= default_root
;
2933 /* Local fixed drives can be cached permanently. Removable drives
2934 cannot be cached permanently, since the volume name and serial
2935 number (if nothing else) can change. Remote drives should be
2936 treated as if they are removable, since there is no sure way to
2937 tell whether they are or not. Also, the UNC association of drive
2938 letters mapped to remote volumes can be changed at any time (even
2939 by other processes) without notice.
2941 As a compromise, so we can benefit from caching info for remote
2942 volumes, we use a simple expiry mechanism to invalidate cache
2943 entries that are more than ten seconds old. */
2946 /* No point doing this, because WNetGetConnection is even slower than
2947 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2948 GetDriveType is about the only call of this type which does not
2949 involve network access, and so is extremely quick). */
2951 /* Map drive letter to UNC if remote. */
2952 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2954 char remote_name
[ 256 ];
2955 char drive
[3] = { root_dir
[0], ':' };
2957 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2959 /* do something */ ;
2963 info
= lookup_volume_info (root_dir
);
2965 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2971 /* Info is not cached, or is stale. */
2972 if (w32_unicode_filenames
)
2974 wchar_t root_w
[MAX_PATH
];
2975 wchar_t name_w
[MAX_PATH
+1];
2976 wchar_t type_w
[MAX_PATH
+1];
2978 filename_to_utf16 (root_dir
, root_w
);
2979 if (!GetVolumeInformationW (root_w
,
2980 name_w
, sizeof (name_w
),
2984 type_w
, sizeof (type_w
)))
2986 /* Hmm... not really 100% correct, as these 2 are not file
2988 filename_from_utf16 (name_w
, name
);
2989 filename_from_utf16 (type_w
, type
);
2993 char root_a
[MAX_PATH
];
2994 char name_a
[MAX_PATH
+1];
2995 char type_a
[MAX_PATH
+1];
2997 filename_to_ansi (root_dir
, root_a
);
2998 if (!GetVolumeInformationA (root_a
,
2999 name_a
, sizeof (name_a
),
3003 type_a
, sizeof (type_a
)))
3005 filename_from_ansi (name_a
, name
);
3006 filename_from_ansi (type_a
, type
);
3009 /* Cache the volume information for future use, overwriting existing
3010 entry if present. */
3013 info
= xmalloc (sizeof (volume_info_data
));
3014 add_volume_info (root_dir
, info
);
3022 info
->name
= xstrdup (name
);
3023 unixtodos_filename (info
->name
);
3024 info
->serialnum
= serialnum
;
3025 info
->maxcomp
= maxcomp
;
3026 info
->flags
= flags
;
3027 info
->type
= xstrdup (type
);
3028 info
->timestamp
= GetTickCount ();
3034 /* Get information on the volume where NAME is held; set path pointer to
3035 start of pathname in NAME (past UNC header\volume header if present),
3036 if pPath is non-NULL.
3038 Note: if NAME includes symlinks, the information is for the volume
3039 of the symlink, not of its target. That's because, even though
3040 GetVolumeInformation returns information about the symlink target
3041 of its argument, we only pass the root directory to
3042 GetVolumeInformation, not the full NAME. */
3044 get_volume_info (const char * name
, const char ** pPath
)
3046 char temp
[MAX_UTF8_PATH
];
3047 char *rootname
= NULL
; /* default to current volume */
3048 volume_info_data
* info
;
3049 int root_len
= parse_root (name
, pPath
);
3054 /* Copy the root name of the volume, if given. */
3057 strncpy (temp
, name
, root_len
);
3058 temp
[root_len
] = '\0';
3059 unixtodos_filename (temp
);
3063 info
= GetCachedVolumeInformation (rootname
);
3066 /* Set global referenced by other functions. */
3067 volume_info
= *info
;
3073 /* Determine if volume is FAT format (ie. only supports short 8.3
3074 names); also set path pointer to start of pathname in name, if
3075 pPath is non-NULL. */
3077 is_fat_volume (const char * name
, const char ** pPath
)
3079 if (get_volume_info (name
, pPath
))
3080 return (volume_info
.maxcomp
== 12);
3084 /* Convert all slashes in a filename to backslashes, and map filename
3085 to a valid 8.3 name if necessary. The result is a pointer to a
3086 static buffer, so CAVEAT EMPTOR! */
3088 map_w32_filename (const char * name
, const char ** pPath
)
3090 static char shortname
[MAX_UTF8_PATH
];
3091 char * str
= shortname
;
3094 const char * save_name
= name
;
3096 if (strlen (name
) >= sizeof (shortname
))
3098 /* Return a filename which will cause callers to fail. */
3099 strcpy (shortname
, "?");
3103 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3105 register int left
= 8; /* maximum number of chars in part */
3106 register int extn
= 0; /* extension added? */
3107 register int dots
= 2; /* maximum number of dots allowed */
3110 *str
++ = *name
++; /* skip past UNC header */
3112 while ((c
= *name
++))
3119 *str
++ = (c
== ':' ? ':' : '\\');
3120 extn
= 0; /* reset extension flags */
3121 dots
= 2; /* max 2 dots */
3122 left
= 8; /* max length 8 for main part */
3127 /* Convert path components of the form .xxx to _xxx,
3128 but leave . and .. as they are. This allows .emacs
3129 to be read as _emacs, for example. */
3133 IS_DIRECTORY_SEP (*name
))
3148 extn
= 1; /* we've got an extension */
3149 left
= 3; /* 3 chars in extension */
3153 /* any embedded dots after the first are converted to _ */
3158 case '#': /* don't lose these, they're important */
3160 str
[-1] = c
; /* replace last character of part */
3163 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3165 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3167 dots
= 0; /* started a path component */
3176 strcpy (shortname
, name
);
3177 unixtodos_filename (shortname
);
3181 *pPath
= shortname
+ (path
- save_name
);
3187 is_exec (const char * name
)
3189 char * p
= strrchr (name
, '.');
3192 && (xstrcasecmp (p
, ".exe") == 0 ||
3193 xstrcasecmp (p
, ".com") == 0 ||
3194 xstrcasecmp (p
, ".bat") == 0 ||
3195 xstrcasecmp (p
, ".cmd") == 0));
3198 /* Emulate the Unix directory procedures opendir, closedir, and
3199 readdir. We rename them to sys_* names because some versions of
3200 MinGW startup code call opendir and readdir to glob wildcards, and
3201 the code that calls them doesn't grok UTF-8 encoded file names we
3202 produce in dirent->d_name[]. */
3204 struct dirent dir_static
; /* simulated directory contents */
3205 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3206 static int dir_is_fat
;
3207 static char dir_pathname
[MAX_UTF8_PATH
];
3208 static WIN32_FIND_DATAW dir_find_data_w
;
3209 static WIN32_FIND_DATAA dir_find_data_a
;
3210 #define DIR_FIND_DATA_W 1
3211 #define DIR_FIND_DATA_A 2
3212 static int last_dir_find_data
= -1;
3214 /* Support shares on a network resource as subdirectories of a read-only
3216 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3217 static HANDLE
open_unc_volume (const char *);
3218 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3219 static void close_unc_volume (HANDLE
);
3222 sys_opendir (const char *filename
)
3226 /* Opening is done by FindFirstFile. However, a read is inherent to
3227 this operation, so we defer the open until read time. */
3229 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3231 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3234 /* Note: We don't support traversal of UNC volumes via symlinks.
3235 Doing so would mean punishing 99.99% of use cases by resolving
3236 all the possible symlinks in FILENAME, recursively. */
3237 if (is_unc_volume (filename
))
3239 wnet_enum_handle
= open_unc_volume (filename
);
3240 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3244 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3251 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3252 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3253 /* Note: We don't support symlinks to file names on FAT volumes.
3254 Doing so would mean punishing 99.99% of use cases by resolving
3255 all the possible symlinks in FILENAME, recursively. */
3256 dir_is_fat
= is_fat_volume (filename
, NULL
);
3262 sys_closedir (DIR *dirp
)
3264 /* If we have a find-handle open, close it. */
3265 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3267 FindClose (dir_find_handle
);
3268 dir_find_handle
= INVALID_HANDLE_VALUE
;
3270 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3272 close_unc_volume (wnet_enum_handle
);
3273 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3275 xfree ((char *) dirp
);
3279 sys_readdir (DIR *dirp
)
3281 int downcase
= !NILP (Vw32_downcase_file_names
);
3283 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3285 if (!read_unc_volume (wnet_enum_handle
,
3286 dir_find_data_w
.cFileName
,
3287 dir_find_data_a
.cFileName
,
3291 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3292 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3294 char filename
[MAX_UTF8_PATH
+ 2];
3297 strcpy (filename
, dir_pathname
);
3298 ln
= strlen (filename
) - 1;
3299 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3300 strcat (filename
, "\\");
3301 strcat (filename
, "*");
3303 /* Note: No need to resolve symlinks in FILENAME, because
3304 FindFirst opens the directory that is the target of a
3306 if (w32_unicode_filenames
)
3308 wchar_t fnw
[MAX_PATH
];
3310 filename_to_utf16 (filename
, fnw
);
3311 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3317 filename_to_ansi (filename
, fna
);
3318 /* If FILENAME is not representable by the current ANSI
3319 codepage, we don't want FindFirstFileA to interpret the
3320 '?' characters as a wildcard. */
3321 if (_mbspbrk (fna
, "?"))
3322 dir_find_handle
= INVALID_HANDLE_VALUE
;
3324 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3327 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3330 else if (w32_unicode_filenames
)
3332 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3337 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3341 /* Emacs never uses this value, so don't bother making it match
3342 value returned by stat(). */
3343 dir_static
.d_ino
= 1;
3345 if (w32_unicode_filenames
)
3347 if (downcase
|| dir_is_fat
)
3349 wchar_t tem
[MAX_PATH
];
3351 wcscpy (tem
, dir_find_data_w
.cFileName
);
3353 filename_from_utf16 (tem
, dir_static
.d_name
);
3356 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3357 last_dir_find_data
= DIR_FIND_DATA_W
;
3363 /* If the file name in cFileName[] includes `?' characters, it
3364 means the original file name used characters that cannot be
3365 represented by the current ANSI codepage. To avoid total
3366 lossage, retrieve the short 8+3 alias of the long file
3368 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3370 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3371 /* 8+3 aliases are returned in all caps, which could break
3372 various alists that look at filenames' extensions. */
3375 else if (downcase
|| dir_is_fat
)
3376 strcpy (tem
, dir_find_data_a
.cFileName
);
3378 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3379 if (downcase
|| dir_is_fat
)
3382 filename_from_ansi (tem
, dir_static
.d_name
);
3384 last_dir_find_data
= DIR_FIND_DATA_A
;
3387 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3388 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3389 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3395 open_unc_volume (const char *path
)
3397 const char *fn
= map_w32_filename (path
, NULL
);
3401 if (w32_unicode_filenames
)
3404 wchar_t fnw
[MAX_PATH
];
3406 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3407 nrw
.dwType
= RESOURCETYPE_DISK
;
3408 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3409 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3410 nrw
.lpLocalName
= NULL
;
3411 filename_to_utf16 (fn
, fnw
);
3412 nrw
.lpRemoteName
= fnw
;
3413 nrw
.lpComment
= NULL
;
3414 nrw
.lpProvider
= NULL
;
3416 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3417 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3424 nra
.dwScope
= RESOURCE_GLOBALNET
;
3425 nra
.dwType
= RESOURCETYPE_DISK
;
3426 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3427 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3428 nra
.lpLocalName
= NULL
;
3429 filename_to_ansi (fn
, fna
);
3430 nra
.lpRemoteName
= fna
;
3431 nra
.lpComment
= NULL
;
3432 nra
.lpProvider
= NULL
;
3434 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3435 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3437 if (result
== NO_ERROR
)
3440 return INVALID_HANDLE_VALUE
;
3444 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3449 DWORD bufsize
= 512;
3453 if (w32_unicode_filenames
)
3458 buffer
= alloca (bufsize
);
3459 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3460 if (result
!= NO_ERROR
)
3462 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3463 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3465 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3467 wcsncpy (fname_w
, ptrw
, size
);
3472 int dbcs_p
= max_filename_mbslen () > 1;
3475 buffer
= alloca (bufsize
);
3476 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3477 if (result
!= NO_ERROR
)
3479 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3482 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3485 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3486 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3489 strncpy (fname_a
, ptra
, size
);
3497 close_unc_volume (HANDLE henum
)
3499 if (henum
!= INVALID_HANDLE_VALUE
)
3500 WNetCloseEnum (henum
);
3504 unc_volume_file_attributes (const char *path
)
3509 henum
= open_unc_volume (path
);
3510 if (henum
== INVALID_HANDLE_VALUE
)
3513 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3515 close_unc_volume (henum
);
3520 /* Ensure a network connection is authenticated. */
3522 logon_network_drive (const char *path
)
3524 char share
[MAX_UTF8_PATH
];
3531 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3532 drvtype
= DRIVE_REMOTE
;
3533 else if (path
[0] == '\0' || path
[1] != ':')
3534 drvtype
= GetDriveType (NULL
);
3541 drvtype
= GetDriveType (drive
);
3544 /* Only logon to networked drives. */
3545 if (drvtype
!= DRIVE_REMOTE
)
3549 strncpy (share
, path
, MAX_UTF8_PATH
);
3550 /* Truncate to just server and share name. */
3551 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3553 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3560 if (w32_unicode_filenames
)
3562 NETRESOURCEW resourcew
;
3563 wchar_t share_w
[MAX_PATH
];
3565 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3566 resourcew
.dwType
= RESOURCETYPE_DISK
;
3567 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3568 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3569 resourcew
.lpLocalName
= NULL
;
3570 filename_to_utf16 (share
, share_w
);
3571 resourcew
.lpRemoteName
= share_w
;
3572 resourcew
.lpProvider
= NULL
;
3574 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3578 NETRESOURCEA resourcea
;
3579 char share_a
[MAX_PATH
];
3581 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3582 resourcea
.dwType
= RESOURCETYPE_DISK
;
3583 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3584 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3585 resourcea
.lpLocalName
= NULL
;
3586 filename_to_ansi (share
, share_a
);
3587 resourcea
.lpRemoteName
= share_a
;
3588 resourcea
.lpProvider
= NULL
;
3590 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3596 case ERROR_ALREADY_ASSIGNED
:
3598 case ERROR_ACCESS_DENIED
:
3599 case ERROR_LOGON_FAILURE
:
3605 case ERROR_BAD_NET_NAME
:
3606 case ERROR_NO_NET_OR_BAD_PATH
:
3607 case ERROR_NO_NETWORK
:
3608 case ERROR_CANCELLED
:
3615 /* Emulate faccessat(2). */
3617 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3621 if (dirfd
!= AT_FDCWD
3622 && !(IS_DIRECTORY_SEP (path
[0])
3623 || IS_DEVICE_SEP (path
[1])))
3629 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3630 newer versions blow up when passed D_OK. */
3631 path
= map_w32_filename (path
, NULL
);
3632 /* If the last element of PATH is a symlink, we need to resolve it
3633 to get the attributes of its target file. Note: any symlinks in
3634 PATH elements other than the last one are transparently resolved
3635 by GetFileAttributes below. */
3636 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3637 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3638 path
= chase_symlinks (path
);
3640 if (w32_unicode_filenames
)
3642 wchar_t path_w
[MAX_PATH
];
3644 filename_to_utf16 (path
, path_w
);
3645 attributes
= GetFileAttributesW (path_w
);
3649 char path_a
[MAX_PATH
];
3651 filename_to_ansi (path
, path_a
);
3652 attributes
= GetFileAttributesA (path_a
);
3655 if (attributes
== -1)
3657 DWORD w32err
= GetLastError ();
3661 case ERROR_INVALID_NAME
:
3662 case ERROR_BAD_PATHNAME
:
3663 if (is_unc_volume (path
))
3665 attributes
= unc_volume_file_attributes (path
);
3666 if (attributes
== -1)
3674 case ERROR_FILE_NOT_FOUND
:
3675 case ERROR_BAD_NETPATH
:
3684 if ((mode
& X_OK
) != 0
3685 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3690 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3695 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3703 /* A version of 'access' to be used locally with file names in
3704 locale-specific encoding. Does not resolve symlinks and does not
3705 support file names on FAT12 and FAT16 volumes, but that's OK, since
3706 we only invoke this function for files inside the Emacs source or
3707 installation tree, on directories (so any symlinks should have the
3708 directory bit set), and on short file names such as "C:/.emacs". */
3710 sys_access (const char *fname
, int mode
)
3712 char fname_copy
[MAX_PATH
], *p
;
3715 strcpy (fname_copy
, fname
);
3716 /* Do the equivalent of unixtodos_filename. */
3717 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3721 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3723 DWORD w32err
= GetLastError ();
3727 case ERROR_INVALID_NAME
:
3728 case ERROR_BAD_PATHNAME
:
3729 case ERROR_FILE_NOT_FOUND
:
3730 case ERROR_BAD_NETPATH
:
3739 if ((mode
& X_OK
) != 0
3740 && !(is_exec (fname_copy
)
3741 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3746 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3751 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3759 /* Shadow some MSVC runtime functions to map requests for long filenames
3760 to reasonable short names if necessary. This was originally added to
3761 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3765 sys_chdir (const char * path
)
3767 path
= map_w32_filename (path
, NULL
);
3768 if (w32_unicode_filenames
)
3770 wchar_t newdir_w
[MAX_PATH
];
3772 if (filename_to_utf16 (path
, newdir_w
) == 0)
3773 return _wchdir (newdir_w
);
3778 char newdir_a
[MAX_PATH
];
3780 if (filename_to_ansi (path
, newdir_a
) == 0)
3781 return _chdir (newdir_a
);
3787 sys_chmod (const char * path
, int mode
)
3789 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3790 if (w32_unicode_filenames
)
3792 wchar_t path_w
[MAX_PATH
];
3794 filename_to_utf16 (path
, path_w
);
3795 return _wchmod (path_w
, mode
);
3799 char path_a
[MAX_PATH
];
3801 filename_to_ansi (path
, path_a
);
3802 return _chmod (path_a
, mode
);
3807 sys_creat (const char * path
, int mode
)
3809 path
= map_w32_filename (path
, NULL
);
3810 if (w32_unicode_filenames
)
3812 wchar_t path_w
[MAX_PATH
];
3814 filename_to_utf16 (path
, path_w
);
3815 return _wcreat (path_w
, mode
);
3819 char path_a
[MAX_PATH
];
3821 filename_to_ansi (path
, path_a
);
3822 return _creat (path_a
, mode
);
3827 sys_fopen (const char * path
, const char * mode
)
3831 const char * mode_save
= mode
;
3833 /* Force all file handles to be non-inheritable. This is necessary to
3834 ensure child processes don't unwittingly inherit handles that might
3835 prevent future file access. */
3839 else if (mode
[0] == 'w' || mode
[0] == 'a')
3840 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3844 /* Only do simplistic option parsing. */
3848 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3851 else if (mode
[0] == 'b')
3856 else if (mode
[0] == 't')
3863 path
= map_w32_filename (path
, NULL
);
3864 if (w32_unicode_filenames
)
3866 wchar_t path_w
[MAX_PATH
];
3868 filename_to_utf16 (path
, path_w
);
3869 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3873 char path_a
[MAX_PATH
];
3875 filename_to_ansi (path
, path_a
);
3876 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3881 return _fdopen (fd
, mode_save
);
3884 /* This only works on NTFS volumes, but is useful to have. */
3886 sys_link (const char * old
, const char * new)
3890 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3891 wchar_t oldname_w
[MAX_PATH
];
3892 char oldname_a
[MAX_PATH
];
3894 if (old
== NULL
|| new == NULL
)
3900 strcpy (oldname
, map_w32_filename (old
, NULL
));
3901 strcpy (newname
, map_w32_filename (new, NULL
));
3903 if (w32_unicode_filenames
)
3905 filename_to_utf16 (oldname
, oldname_w
);
3906 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
3907 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3911 filename_to_ansi (oldname
, oldname_a
);
3912 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
3913 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3915 if (fileh
!= INVALID_HANDLE_VALUE
)
3919 /* Confusingly, the "alternate" stream name field does not apply
3920 when restoring a hard link, and instead contains the actual
3921 stream data for the link (ie. the name of the link to create).
3922 The WIN32_STREAM_ID structure before the cStreamName field is
3923 the stream header, which is then immediately followed by the
3927 WIN32_STREAM_ID wid
;
3928 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3931 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
3932 indicates that flag is unsupported for CP_UTF8, and OTOH says
3933 it is the default anyway. */
3934 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
3935 data
.wid
.cStreamName
, MAX_PATH
);
3938 LPVOID context
= NULL
;
3941 data
.wid
.dwStreamId
= BACKUP_LINK
;
3942 data
.wid
.dwStreamAttributes
= 0;
3943 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3944 data
.wid
.Size
.HighPart
= 0;
3945 data
.wid
.dwStreamNameSize
= 0;
3947 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3948 offsetof (WIN32_STREAM_ID
, cStreamName
)
3949 + data
.wid
.Size
.LowPart
,
3950 &wbytes
, FALSE
, FALSE
, &context
)
3951 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3958 DWORD err
= GetLastError ();
3963 case ERROR_ACCESS_DENIED
:
3964 /* This is what happens when OLDNAME is a directory,
3965 since Windows doesn't support hard links to
3966 directories. Posix says to set errno to EPERM in
3968 if (w32_unicode_filenames
)
3969 attributes
= GetFileAttributesW (oldname_w
);
3971 attributes
= GetFileAttributesA (oldname_a
);
3972 if (attributes
!= -1
3973 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
3975 else if (attributes
== -1
3976 && is_unc_volume (oldname
)
3977 && unc_volume_file_attributes (oldname
) != -1)
3982 case ERROR_TOO_MANY_LINKS
:
3985 case ERROR_NOT_SAME_DEVICE
:
3995 CloseHandle (fileh
);
4004 sys_mkdir (const char * path
)
4006 path
= map_w32_filename (path
, NULL
);
4008 if (w32_unicode_filenames
)
4010 wchar_t path_w
[MAX_PATH
];
4012 filename_to_utf16 (path
, path_w
);
4013 return _wmkdir (path_w
);
4017 char path_a
[MAX_PATH
];
4019 filename_to_ansi (path
, path_a
);
4020 return _mkdir (path_a
);
4025 sys_open (const char * path
, int oflag
, int mode
)
4027 const char* mpath
= map_w32_filename (path
, NULL
);
4030 if (w32_unicode_filenames
)
4032 wchar_t mpath_w
[MAX_PATH
];
4034 filename_to_utf16 (mpath
, mpath_w
);
4035 /* If possible, try to open file without _O_CREAT, to be able to
4036 write to existing hidden and system files. Force all file
4037 handles to be non-inheritable. */
4038 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4039 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4041 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4045 char mpath_a
[MAX_PATH
];
4047 filename_to_ansi (mpath
, mpath_a
);
4048 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4049 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4051 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4057 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4060 Standard algorithm for generating a temporary file name seems to be
4061 use pid or tid with a letter on the front (in place of the 6 X's)
4062 and cycle through the letters to find a unique name. We extend
4063 that to allow any reasonable character as the first of the 6 X's,
4064 so that the number of simultaneously used temporary files will be
4068 mkostemp (char * template, int flags
)
4072 unsigned uid
= GetCurrentThreadId ();
4073 int save_errno
= errno
;
4074 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4077 if (template == NULL
)
4080 p
= template + strlen (template);
4082 /* replace up to the last 5 X's with uid in decimal */
4083 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4085 p
[0] = '0' + uid
% 10;
4089 if (i
< 0 && p
[0] == 'X')
4094 p
[0] = first_char
[i
];
4095 if ((fd
= sys_open (template,
4096 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4097 S_IRUSR
| S_IWUSR
)) >= 0
4105 while (++i
< sizeof (first_char
));
4108 /* Template is badly formed or else we can't generate a unique name. */
4113 fchmod (int fd
, mode_t mode
)
4119 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4122 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4125 bool have_temp_a
= false;
4127 /* MoveFile on Windows 95 doesn't correctly change the short file name
4128 alias in a number of circumstances (it is not easy to predict when
4129 just by looking at oldname and newname, unfortunately). In these
4130 cases, renaming through a temporary name avoids the problem.
4132 A second problem on Windows 95 is that renaming through a temp name when
4133 newname is uppercase fails (the final long name ends up in
4134 lowercase, although the short alias might be uppercase) UNLESS the
4135 long temp name is not 8.3.
4137 So, on Windows 95 we always rename through a temp name, and we make sure
4138 the temp name has a long extension to ensure correct renaming. */
4140 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4142 /* volume_info is set indirectly by map_w32_filename. */
4143 oldname_dev
= volume_info
.serialnum
;
4145 if (os_subtype
== OS_9X
)
4150 char oldname_a
[MAX_PATH
];
4152 oldname
= map_w32_filename (oldname
, NULL
);
4153 filename_to_ansi (oldname
, oldname_a
);
4154 filename_to_ansi (temp
, temp_a
);
4155 if ((o
= strrchr (oldname_a
, '\\')))
4158 o
= (char *) oldname_a
;
4160 if ((p
= strrchr (temp_a
, '\\')))
4167 /* Force temp name to require a manufactured 8.3 alias - this
4168 seems to make the second rename work properly. */
4169 sprintf (p
, "_.%s.%u", o
, i
);
4171 result
= rename (oldname_a
, temp_a
);
4173 /* This loop must surely terminate! */
4174 while (result
< 0 && errno
== EEXIST
);
4180 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4181 (at least if it is a file; don't do this for directories).
4183 Since we mustn't do this if we are just changing the case of the
4184 file name (we would end up deleting the file we are trying to
4185 rename!), we let rename detect if the destination file already
4186 exists - that way we avoid the possible pitfalls of trying to
4187 determine ourselves whether two names really refer to the same
4188 file, which is not always possible in the general case. (Consider
4189 all the permutations of shared or subst'd drives, etc.) */
4191 newname
= map_w32_filename (newname
, NULL
);
4193 /* volume_info is set indirectly by map_w32_filename. */
4194 newname_dev
= volume_info
.serialnum
;
4196 if (w32_unicode_filenames
)
4198 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4200 filename_to_utf16 (temp
, temp_w
);
4201 filename_to_utf16 (newname
, newname_w
);
4202 result
= _wrename (temp_w
, newname_w
);
4203 if (result
< 0 && force
)
4205 DWORD w32err
= GetLastError ();
4208 && newname_dev
!= oldname_dev
)
4210 /* The implementation of `rename' on Windows does not return
4211 errno = EXDEV when you are moving a directory to a
4212 different storage device (ex. logical disk). It returns
4213 EACCES instead. So here we handle such situations and
4217 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4218 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4221 else if (errno
== EEXIST
)
4223 if (_wchmod (newname_w
, 0666) != 0)
4225 if (_wunlink (newname_w
) != 0)
4227 result
= _wrename (temp_w
, newname_w
);
4229 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4230 && is_symlink (temp
))
4232 /* This is Windows prohibiting the user from creating a
4233 symlink in another place, since that requires
4241 char newname_a
[MAX_PATH
];
4244 filename_to_ansi (temp
, temp_a
);
4245 filename_to_ansi (newname
, newname_a
);
4246 result
= rename (temp_a
, newname_a
);
4247 if (result
< 0 && force
)
4249 DWORD w32err
= GetLastError ();
4252 && newname_dev
!= oldname_dev
)
4256 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4257 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4260 else if (errno
== EEXIST
)
4262 if (_chmod (newname_a
, 0666) != 0)
4264 if (_unlink (newname_a
) != 0)
4266 result
= rename (temp_a
, newname_a
);
4268 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4269 && is_symlink (temp
))
4278 sys_rename (char const *old
, char const *new)
4280 return sys_rename_replace (old
, new, TRUE
);
4284 sys_rmdir (const char * path
)
4286 path
= map_w32_filename (path
, NULL
);
4288 if (w32_unicode_filenames
)
4290 wchar_t path_w
[MAX_PATH
];
4292 filename_to_utf16 (path
, path_w
);
4293 return _wrmdir (path_w
);
4297 char path_a
[MAX_PATH
];
4299 filename_to_ansi (path
, path_a
);
4300 return _rmdir (path_a
);
4305 sys_unlink (const char * path
)
4307 path
= map_w32_filename (path
, NULL
);
4309 if (w32_unicode_filenames
)
4311 wchar_t path_w
[MAX_PATH
];
4313 filename_to_utf16 (path
, path_w
);
4314 /* On Unix, unlink works without write permission. */
4315 _wchmod (path_w
, 0666);
4316 return _wunlink (path_w
);
4320 char path_a
[MAX_PATH
];
4322 filename_to_ansi (path
, path_a
);
4323 _chmod (path_a
, 0666);
4324 return _unlink (path_a
);
4328 static FILETIME utc_base_ft
;
4329 static ULONGLONG utc_base
; /* In 100ns units */
4330 static int init
= 0;
4332 #define FILETIME_TO_U64(result, ft) \
4334 ULARGE_INTEGER uiTemp; \
4335 uiTemp.LowPart = (ft).dwLowDateTime; \
4336 uiTemp.HighPart = (ft).dwHighDateTime; \
4337 result = uiTemp.QuadPart; \
4341 initialize_utc_base (void)
4343 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4352 st
.wMilliseconds
= 0;
4354 SystemTimeToFileTime (&st
, &utc_base_ft
);
4355 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4359 convert_time (FILETIME ft
)
4365 initialize_utc_base ();
4369 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4372 FILETIME_TO_U64 (tmp
, ft
);
4373 return (time_t) ((tmp
- utc_base
) / 10000000L);
4377 convert_from_time_t (time_t time
, FILETIME
* pft
)
4383 initialize_utc_base ();
4387 /* time in 100ns units since 1-Jan-1601 */
4388 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4389 pft
->dwHighDateTime
= tmp
.HighPart
;
4390 pft
->dwLowDateTime
= tmp
.LowPart
;
4393 static PSECURITY_DESCRIPTOR
4394 get_file_security_desc_by_handle (HANDLE h
)
4396 PSECURITY_DESCRIPTOR psd
= NULL
;
4398 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4399 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4401 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4402 NULL
, NULL
, NULL
, NULL
, &psd
);
4403 if (err
!= ERROR_SUCCESS
)
4409 static PSECURITY_DESCRIPTOR
4410 get_file_security_desc_by_name (const char *fname
)
4412 PSECURITY_DESCRIPTOR psd
= NULL
;
4414 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4415 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4417 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4419 err
= GetLastError ();
4420 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4424 psd
= xmalloc (sd_len
);
4425 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4437 unsigned n_subauthorities
;
4439 /* Use the last sub-authority value of the RID, the relative
4440 portion of the SID, as user/group ID. */
4441 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4442 if (n_subauthorities
< 1)
4443 return 0; /* the "World" RID */
4444 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4447 /* Caching SID and account values for faster lokup. */
4451 struct w32_id
*next
;
4453 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4456 static struct w32_id
*w32_idlist
;
4459 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4461 struct w32_id
*tail
, *found
;
4463 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4465 if (equal_sid ((PSID
)tail
->sid
, sid
))
4474 strcpy (name
, found
->name
);
4482 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4485 struct w32_id
*new_entry
;
4487 /* We don't want to leave behind stale cache from when Emacs was
4491 sid_len
= get_length_sid (sid
);
4492 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4495 new_entry
->rid
= id
;
4496 strcpy (new_entry
->name
, name
);
4497 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4498 new_entry
->next
= w32_idlist
;
4499 w32_idlist
= new_entry
;
4508 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4512 SID_NAME_USE ignore
;
4514 DWORD name_len
= sizeof (name
);
4516 DWORD domain_len
= sizeof (domain
);
4521 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4522 else if (what
== GID
)
4523 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4527 if (!result
|| !is_valid_sid (sid
))
4529 else if (!w32_cached_id (sid
, id
, nm
))
4531 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4532 domain
, &domain_len
, &ignore
)
4533 || name_len
> UNLEN
+1)
4537 *id
= get_rid (sid
);
4539 w32_add_to_cache (sid
, *id
, name
);
4546 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4548 int dflt_usr
= 0, dflt_grp
= 0;
4557 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4559 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4562 /* Consider files to belong to current user/group, if we cannot get
4563 more accurate information. */
4566 st
->st_uid
= dflt_passwd
.pw_uid
;
4567 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4571 st
->st_gid
= dflt_passwd
.pw_gid
;
4572 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4576 /* Return non-zero if NAME is a potentially slow filesystem. */
4578 is_slow_fs (const char *name
)
4583 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4584 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4585 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4586 devtype
= GetDriveType (NULL
); /* use root of current drive */
4589 /* GetDriveType needs the root directory of the drive. */
4590 strncpy (drive_root
, name
, 2);
4591 drive_root
[2] = '\\';
4592 drive_root
[3] = '\0';
4593 devtype
= GetDriveType (drive_root
);
4595 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4598 /* If this is non-zero, the caller wants accurate information about
4599 file's owner and group, which could be expensive to get. dired.c
4600 uses this flag when needed for the job at hand. */
4601 int w32_stat_get_owner_group
;
4603 /* MSVC stat function can't cope with UNC names and has other bugs, so
4604 replace it with our own. This also allows us to calculate consistent
4605 inode values and owner/group without hacks in the main Emacs code,
4606 and support file names encoded in UTF-8. */
4609 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4611 char *name
, *save_name
, *r
;
4612 WIN32_FIND_DATAW wfd_w
;
4613 WIN32_FIND_DATAA wfd_a
;
4615 unsigned __int64 fake_inode
= 0;
4618 int rootdir
= FALSE
;
4619 PSECURITY_DESCRIPTOR psd
= NULL
;
4620 int is_a_symlink
= 0;
4621 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4622 DWORD access_rights
= 0;
4623 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4624 FILETIME ctime
, atime
, wtime
;
4625 wchar_t name_w
[MAX_PATH
];
4626 char name_a
[MAX_PATH
];
4628 if (path
== NULL
|| buf
== NULL
)
4634 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4635 /* Must be valid filename, no wild cards or other invalid
4637 if (strpbrk (name
, "*?|<>\""))
4643 /* Remove trailing directory separator, unless name is the root
4644 directory of a drive or UNC volume in which case ensure there
4645 is a trailing separator. */
4646 len
= strlen (name
);
4647 name
= strcpy (alloca (len
+ 2), name
);
4649 /* Avoid a somewhat costly call to is_symlink if the filesystem
4650 doesn't support symlinks. */
4651 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4652 is_a_symlink
= is_symlink (name
);
4654 /* Plan A: Open the file and get all the necessary information via
4655 the resulting handle. This solves several issues in one blow:
4657 . retrieves attributes for the target of a symlink, if needed
4658 . gets attributes of root directories and symlinks pointing to
4659 root directories, thus avoiding the need for special-casing
4660 these and detecting them by examining the file-name format
4661 . retrieves more accurate attributes (e.g., non-zero size for
4662 some directories, esp. directories that are junction points)
4663 . correctly resolves "c:/..", "/.." and similar file names
4664 . avoids run-time penalties for 99% of use cases
4666 Plan A is always tried first, unless the user asked not to (but
4667 if the file is a symlink and we need to follow links, we try Plan
4668 A even if the user asked not to).
4670 If Plan A fails, we go to Plan B (below), where various
4671 potentially expensive techniques must be used to handle "special"
4672 files such as UNC volumes etc. */
4673 if (!(NILP (Vw32_get_true_file_attributes
)
4674 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4675 /* Following symlinks requires getting the info by handle. */
4676 || (is_a_symlink
&& follow_symlinks
))
4678 BY_HANDLE_FILE_INFORMATION info
;
4680 if (is_a_symlink
&& !follow_symlinks
)
4681 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4682 /* READ_CONTROL access rights are required to get security info
4683 by handle. But if the OS doesn't support security in the
4684 first place, we don't need to try. */
4685 if (is_windows_9x () != TRUE
)
4686 access_rights
|= READ_CONTROL
;
4688 if (w32_unicode_filenames
)
4690 filename_to_utf16 (name
, name_w
);
4691 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4693 /* If CreateFile fails with READ_CONTROL, try again with
4694 zero as access rights. */
4695 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4696 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4701 filename_to_ansi (name
, name_a
);
4702 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4704 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4705 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4708 if (fh
== INVALID_HANDLE_VALUE
)
4709 goto no_true_file_attributes
;
4711 /* This is more accurate in terms of getting the correct number
4712 of links, but is quite slow (it is noticeable when Emacs is
4713 making a list of file name completions). */
4714 if (GetFileInformationByHandle (fh
, &info
))
4716 nlinks
= info
.nNumberOfLinks
;
4717 /* Might as well use file index to fake inode values, but this
4718 is not guaranteed to be unique unless we keep a handle open
4719 all the time (even then there are situations where it is
4720 not unique). Reputedly, there are at most 48 bits of info
4721 (on NTFS, presumably less on FAT). */
4722 fake_inode
= info
.nFileIndexHigh
;
4724 fake_inode
+= info
.nFileIndexLow
;
4725 serialnum
= info
.dwVolumeSerialNumber
;
4726 fs_high
= info
.nFileSizeHigh
;
4727 fs_low
= info
.nFileSizeLow
;
4728 ctime
= info
.ftCreationTime
;
4729 atime
= info
.ftLastAccessTime
;
4730 wtime
= info
.ftLastWriteTime
;
4731 fattrs
= info
.dwFileAttributes
;
4735 /* We don't go to Plan B here, because it's not clear that
4736 it's a good idea. The only known use case where
4737 CreateFile succeeds, but GetFileInformationByHandle fails
4738 (with ERROR_INVALID_FUNCTION) is for character devices
4739 such as NUL, PRN, etc. For these, switching to Plan B is
4740 a net loss, because we lose the character device
4741 attribute returned by GetFileType below (FindFirstFile
4742 doesn't set that bit in the attributes), and the other
4743 fields don't make sense for character devices anyway.
4744 Emacs doesn't really care for non-file entities in the
4745 context of l?stat, so neither do we. */
4747 /* w32err is assigned so one could put a breakpoint here and
4748 examine its value, when GetFileInformationByHandle
4750 DWORD w32err
= GetLastError ();
4754 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4760 /* Test for a symlink before testing for a directory, since
4761 symlinks to directories have the directory bit set, but we
4762 don't want them to appear as directories. */
4763 if (is_a_symlink
&& !follow_symlinks
)
4764 buf
->st_mode
= S_IFLNK
;
4765 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4766 buf
->st_mode
= S_IFDIR
;
4769 DWORD ftype
= GetFileType (fh
);
4773 case FILE_TYPE_DISK
:
4774 buf
->st_mode
= S_IFREG
;
4776 case FILE_TYPE_PIPE
:
4777 buf
->st_mode
= S_IFIFO
;
4779 case FILE_TYPE_CHAR
:
4780 case FILE_TYPE_UNKNOWN
:
4782 buf
->st_mode
= S_IFCHR
;
4785 /* We produce the fallback owner and group data, based on the
4786 current user that runs Emacs, in the following cases:
4788 . caller didn't request owner and group info
4789 . this is Windows 9X
4790 . getting security by handle failed, and we need to produce
4791 information for the target of a symlink (this is better
4792 than producing a potentially misleading info about the
4795 If getting security by handle fails, and we don't need to
4796 resolve symlinks, we try getting security by name. */
4797 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4798 get_file_owner_and_group (NULL
, buf
);
4801 psd
= get_file_security_desc_by_handle (fh
);
4804 get_file_owner_and_group (psd
, buf
);
4807 else if (!(is_a_symlink
&& follow_symlinks
))
4809 psd
= get_file_security_desc_by_name (name
);
4810 get_file_owner_and_group (psd
, buf
);
4814 get_file_owner_and_group (NULL
, buf
);
4820 no_true_file_attributes
:
4821 /* Plan B: Either getting a handle on the file failed, or the
4822 caller explicitly asked us to not bother making this
4823 information more accurate.
4825 Implementation note: In Plan B, we never bother to resolve
4826 symlinks, even if we got here because we tried Plan A and
4827 failed. That's because, even if the caller asked for extra
4828 precision by setting Vw32_get_true_file_attributes to t,
4829 resolving symlinks requires acquiring a file handle to the
4830 symlink, which we already know will fail. And if the user
4831 did not ask for extra precision, resolving symlinks will fly
4832 in the face of that request, since the user then wants the
4833 lightweight version of the code. */
4834 rootdir
= (path
>= save_name
+ len
- 1
4835 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4837 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4838 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4839 if (IS_DIRECTORY_SEP (r
[0])
4840 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4843 /* Note: If NAME is a symlink to the root of a UNC volume
4844 (i.e. "\\SERVER"), we will not detect that here, and we will
4845 return data about the symlink as result of FindFirst below.
4846 This is unfortunate, but that marginal use case does not
4847 justify a call to chase_symlinks which would impose a penalty
4848 on all the other use cases. (We get here for symlinks to
4849 roots of UNC volumes because CreateFile above fails for them,
4850 unlike with symlinks to root directories X:\ of drives.) */
4851 if (is_unc_volume (name
))
4853 fattrs
= unc_volume_file_attributes (name
);
4857 ctime
= atime
= wtime
= utc_base_ft
;
4861 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4862 strcat (name
, "\\");
4863 if (GetDriveType (name
) < 2)
4869 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4870 ctime
= atime
= wtime
= utc_base_ft
;
4876 if (IS_DIRECTORY_SEP (name
[len
-1]))
4879 /* (This is hacky, but helps when doing file completions on
4880 network drives.) Optimize by using information available from
4881 active readdir if possible. */
4882 len
= strlen (dir_pathname
);
4883 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4885 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4886 && last_dir_find_data
!= -1
4887 && !(is_a_symlink
&& follow_symlinks
)
4888 /* The 2 file-name comparisons below support only ASCII
4889 characters, and will lose (compare not equal) when
4890 the file names include non-ASCII charcaters that are
4891 the same but for the case. However, doing this
4892 properly involves: (a) converting both file names to
4893 UTF-16, (b) lower-casing both names using CharLowerW,
4894 and (c) comparing the results; this would be quite a
4895 bit slower, whereas Plan B is for users who want
4896 lightweight albeit inaccurate version of 'stat'. */
4897 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
4898 && IS_DIRECTORY_SEP (name
[len
])
4899 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4901 have_wfd
= last_dir_find_data
;
4902 /* This was the last entry returned by readdir. */
4903 if (last_dir_find_data
== DIR_FIND_DATA_W
)
4904 wfd_w
= dir_find_data_w
;
4906 wfd_a
= dir_find_data_a
;
4910 logon_network_drive (name
);
4912 if (w32_unicode_filenames
)
4914 filename_to_utf16 (name
, name_w
);
4915 fh
= FindFirstFileW (name_w
, &wfd_w
);
4916 have_wfd
= DIR_FIND_DATA_W
;
4920 filename_to_ansi (name
, name_a
);
4921 /* If NAME includes characters not representable by
4922 the current ANSI codepage, filename_to_ansi
4923 usually replaces them with a '?'. We don't want
4924 to let FindFirstFileA interpret those as widlcards,
4925 and "succeed", returning us data from some random
4926 file in the same directory. */
4927 if (_mbspbrk (name_a
, "?"))
4928 fh
= INVALID_HANDLE_VALUE
;
4930 fh
= FindFirstFileA (name_a
, &wfd_a
);
4931 have_wfd
= DIR_FIND_DATA_A
;
4933 if (fh
== INVALID_HANDLE_VALUE
)
4940 /* Note: if NAME is a symlink, the information we get from
4941 FindFirstFile is for the symlink, not its target. */
4942 if (have_wfd
== DIR_FIND_DATA_W
)
4944 fattrs
= wfd_w
.dwFileAttributes
;
4945 ctime
= wfd_w
.ftCreationTime
;
4946 atime
= wfd_w
.ftLastAccessTime
;
4947 wtime
= wfd_w
.ftLastWriteTime
;
4948 fs_high
= wfd_w
.nFileSizeHigh
;
4949 fs_low
= wfd_w
.nFileSizeLow
;
4953 fattrs
= wfd_a
.dwFileAttributes
;
4954 ctime
= wfd_a
.ftCreationTime
;
4955 atime
= wfd_a
.ftLastAccessTime
;
4956 wtime
= wfd_a
.ftLastWriteTime
;
4957 fs_high
= wfd_a
.nFileSizeHigh
;
4958 fs_low
= wfd_a
.nFileSizeLow
;
4962 serialnum
= volume_info
.serialnum
;
4964 if (is_a_symlink
&& !follow_symlinks
)
4965 buf
->st_mode
= S_IFLNK
;
4966 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4967 buf
->st_mode
= S_IFDIR
;
4969 buf
->st_mode
= S_IFREG
;
4971 get_file_owner_and_group (NULL
, buf
);
4974 buf
->st_ino
= fake_inode
;
4976 buf
->st_dev
= serialnum
;
4977 buf
->st_rdev
= serialnum
;
4979 buf
->st_size
= fs_high
;
4980 buf
->st_size
<<= 32;
4981 buf
->st_size
+= fs_low
;
4982 buf
->st_nlink
= nlinks
;
4984 /* Convert timestamps to Unix format. */
4985 buf
->st_mtime
= convert_time (wtime
);
4986 buf
->st_atime
= convert_time (atime
);
4987 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4988 buf
->st_ctime
= convert_time (ctime
);
4989 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4991 /* determine rwx permissions */
4992 if (is_a_symlink
&& !follow_symlinks
)
4993 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
4996 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
4997 permission
= S_IREAD
;
4999 permission
= S_IREAD
| S_IWRITE
;
5001 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5002 permission
|= S_IEXEC
;
5003 else if (is_exec (name
))
5004 permission
|= S_IEXEC
;
5007 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5013 stat (const char * path
, struct stat
* buf
)
5015 return stat_worker (path
, buf
, 1);
5019 lstat (const char * path
, struct stat
* buf
)
5021 return stat_worker (path
, buf
, 0);
5025 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5027 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5028 This is good enough for the current usage in Emacs, but is fragile.
5030 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5031 Gnulib does this and can serve as a model. */
5032 char fullname
[MAX_UTF8_PATH
];
5036 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5039 errno
= ENAMETOOLONG
;
5045 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5048 /* Provide fstat and utime as well as stat for consistent handling of
5051 fstat (int desc
, struct stat
* buf
)
5053 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5054 BY_HANDLE_FILE_INFORMATION info
;
5055 unsigned __int64 fake_inode
;
5058 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5060 case FILE_TYPE_DISK
:
5061 buf
->st_mode
= S_IFREG
;
5062 if (!GetFileInformationByHandle (fh
, &info
))
5068 case FILE_TYPE_PIPE
:
5069 buf
->st_mode
= S_IFIFO
;
5071 case FILE_TYPE_CHAR
:
5072 case FILE_TYPE_UNKNOWN
:
5074 buf
->st_mode
= S_IFCHR
;
5076 memset (&info
, 0, sizeof (info
));
5077 info
.dwFileAttributes
= 0;
5078 info
.ftCreationTime
= utc_base_ft
;
5079 info
.ftLastAccessTime
= utc_base_ft
;
5080 info
.ftLastWriteTime
= utc_base_ft
;
5083 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5084 buf
->st_mode
= S_IFDIR
;
5086 buf
->st_nlink
= info
.nNumberOfLinks
;
5087 /* Might as well use file index to fake inode values, but this
5088 is not guaranteed to be unique unless we keep a handle open
5089 all the time (even then there are situations where it is
5090 not unique). Reputedly, there are at most 48 bits of info
5091 (on NTFS, presumably less on FAT). */
5092 fake_inode
= info
.nFileIndexHigh
;
5094 fake_inode
+= info
.nFileIndexLow
;
5096 /* MSVC defines _ino_t to be short; other libc's might not. */
5097 if (sizeof (buf
->st_ino
) == 2)
5098 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5100 buf
->st_ino
= fake_inode
;
5102 /* If the caller so requested, get the true file owner and group.
5103 Otherwise, consider the file to belong to the current user. */
5104 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5105 get_file_owner_and_group (NULL
, buf
);
5108 PSECURITY_DESCRIPTOR psd
= NULL
;
5110 psd
= get_file_security_desc_by_handle (fh
);
5113 get_file_owner_and_group (psd
, buf
);
5117 get_file_owner_and_group (NULL
, buf
);
5120 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5121 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5123 buf
->st_size
= info
.nFileSizeHigh
;
5124 buf
->st_size
<<= 32;
5125 buf
->st_size
+= info
.nFileSizeLow
;
5127 /* Convert timestamps to Unix format. */
5128 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5129 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5130 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5131 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5132 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5134 /* determine rwx permissions */
5135 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5136 permission
= S_IREAD
;
5138 permission
= S_IREAD
| S_IWRITE
;
5140 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5141 permission
|= S_IEXEC
;
5144 #if 0 /* no way of knowing the filename */
5145 char * p
= strrchr (name
, '.');
5147 (xstrcasecmp (p
, ".exe") == 0 ||
5148 xstrcasecmp (p
, ".com") == 0 ||
5149 xstrcasecmp (p
, ".bat") == 0 ||
5150 xstrcasecmp (p
, ".cmd") == 0))
5151 permission
|= S_IEXEC
;
5155 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5160 /* A version of 'utime' which handles directories as well as
5164 utime (const char *name
, struct utimbuf
*times
)
5166 struct utimbuf deftime
;
5173 deftime
.modtime
= deftime
.actime
= time (NULL
);
5177 if (w32_unicode_filenames
)
5179 wchar_t name_utf16
[MAX_PATH
];
5181 if (filename_to_utf16 (name
, name_utf16
) != 0)
5182 return -1; /* errno set by filename_to_utf16 */
5184 /* Need write access to set times. */
5185 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5186 /* If NAME specifies a directory, FILE_SHARE_DELETE
5187 allows other processes to delete files inside it,
5188 while we have the directory open. */
5189 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5190 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5194 char name_ansi
[MAX_PATH
];
5196 if (filename_to_ansi (name
, name_ansi
) != 0)
5197 return -1; /* errno set by filename_to_ansi */
5199 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5200 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5201 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5203 if (fh
!= INVALID_HANDLE_VALUE
)
5205 convert_from_time_t (times
->actime
, &atime
);
5206 convert_from_time_t (times
->modtime
, &mtime
);
5207 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5217 DWORD err
= GetLastError ();
5221 case ERROR_FILE_NOT_FOUND
:
5222 case ERROR_PATH_NOT_FOUND
:
5223 case ERROR_INVALID_DRIVE
:
5224 case ERROR_BAD_NETPATH
:
5225 case ERROR_DEV_NOT_EXIST
:
5226 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5227 file name includes ?s, i.e. translation to ANSI failed. */
5228 case ERROR_INVALID_NAME
:
5231 case ERROR_TOO_MANY_OPEN_FILES
:
5234 case ERROR_ACCESS_DENIED
:
5235 case ERROR_SHARING_VIOLATION
:
5248 /* Symlink-related functions. */
5249 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5250 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5254 symlink (char const *filename
, char const *linkname
)
5256 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5258 int dir_access
, filename_ends_in_slash
;
5260 /* Diagnostics follows Posix as much as possible. */
5261 if (filename
== NULL
|| linkname
== NULL
)
5271 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5273 errno
= ENAMETOOLONG
;
5277 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5278 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5284 /* Note: since empty FILENAME was already rejected, we can safely
5285 refer to FILENAME[1]. */
5286 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5288 /* Non-absolute FILENAME is understood as being relative to
5289 LINKNAME's directory. We need to prepend that directory to
5290 FILENAME to get correct results from faccessat below, since
5291 otherwise it will interpret FILENAME relative to the
5292 directory where the Emacs process runs. Note that
5293 make-symbolic-link always makes sure LINKNAME is a fully
5294 expanded file name. */
5295 char tem
[MAX_UTF8_PATH
];
5296 char *p
= linkfn
+ strlen (linkfn
);
5298 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5301 strncpy (tem
, linkfn
, p
- linkfn
);
5302 tem
[p
- linkfn
] = '\0';
5303 strcat (tem
, filename
);
5304 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5307 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5309 /* Since Windows distinguishes between symlinks to directories and
5310 to files, we provide a kludgy feature: if FILENAME doesn't
5311 exist, but ends in a slash, we create a symlink to directory. If
5312 FILENAME exists and is a directory, we always create a symlink to
5314 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5315 if (dir_access
== 0 || filename_ends_in_slash
)
5316 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5318 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5319 if (filename_ends_in_slash
)
5320 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5323 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5325 /* ENOSYS is set by create_symbolic_link, when it detects that
5326 the OS doesn't support the CreateSymbolicLink API. */
5327 if (errno
!= ENOSYS
)
5329 DWORD w32err
= GetLastError ();
5333 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5334 TGTFN point to the same file name, go figure. */
5336 case ERROR_FILE_EXISTS
:
5339 case ERROR_ACCESS_DENIED
:
5342 case ERROR_FILE_NOT_FOUND
:
5343 case ERROR_PATH_NOT_FOUND
:
5344 case ERROR_BAD_NETPATH
:
5345 case ERROR_INVALID_REPARSE_DATA
:
5348 case ERROR_DIRECTORY
:
5351 case ERROR_PRIVILEGE_NOT_HELD
:
5352 case ERROR_NOT_ALL_ASSIGNED
:
5355 case ERROR_DISK_FULL
:
5368 /* A quick inexpensive test of whether FILENAME identifies a file that
5369 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5370 must already be in the normalized form returned by
5373 Note: for repeated operations on many files, it is best to test
5374 whether the underlying volume actually supports symlinks, by
5375 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5376 avoid the call to this function if it doesn't. That's because the
5377 call to GetFileAttributes takes a non-negligible time, especially
5378 on non-local or removable filesystems. See stat_worker for an
5379 example of how to do that. */
5381 is_symlink (const char *filename
)
5384 wchar_t filename_w
[MAX_PATH
];
5385 char filename_a
[MAX_PATH
];
5386 WIN32_FIND_DATAW wfdw
;
5387 WIN32_FIND_DATAA wfda
;
5389 int attrs_mean_symlink
;
5391 if (w32_unicode_filenames
)
5393 filename_to_utf16 (filename
, filename_w
);
5394 attrs
= GetFileAttributesW (filename_w
);
5398 filename_to_ansi (filename
, filename_a
);
5399 attrs
= GetFileAttributesA (filename_a
);
5403 DWORD w32err
= GetLastError ();
5407 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5409 case ERROR_ACCESS_DENIED
:
5412 case ERROR_FILE_NOT_FOUND
:
5413 case ERROR_PATH_NOT_FOUND
:
5420 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5422 logon_network_drive (filename
);
5423 if (w32_unicode_filenames
)
5425 fh
= FindFirstFileW (filename_w
, &wfdw
);
5426 attrs_mean_symlink
=
5427 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5428 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5430 else if (_mbspbrk (filename_a
, "?"))
5432 /* filename_to_ansi failed to convert the file name. */
5438 fh
= FindFirstFileA (filename_a
, &wfda
);
5439 attrs_mean_symlink
=
5440 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5441 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5443 if (fh
== INVALID_HANDLE_VALUE
)
5446 return attrs_mean_symlink
;
5449 /* If NAME identifies a symbolic link, copy into BUF the file name of
5450 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5451 null-terminate the target name, even if it fits. Return the number
5452 of bytes copied, or -1 if NAME is not a symlink or any error was
5453 encountered while resolving it. The file name copied into BUF is
5454 encoded in the current ANSI codepage. */
5456 readlink (const char *name
, char *buf
, size_t buf_size
)
5459 TOKEN_PRIVILEGES privs
;
5460 int restore_privs
= 0;
5463 char resolved
[MAX_UTF8_PATH
];
5476 path
= map_w32_filename (name
, NULL
);
5478 if (strlen (path
) > MAX_UTF8_PATH
)
5480 errno
= ENAMETOOLONG
;
5485 if (is_windows_9x () == TRUE
5486 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5487 || !is_symlink (path
))
5490 errno
= EINVAL
; /* not a symlink */
5494 /* Done with simple tests, now we're in for some _real_ work. */
5495 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5497 /* Implementation note: From here and onward, don't return early,
5498 since that will fail to restore the original set of privileges of
5499 the calling thread. */
5501 retval
= -1; /* not too optimistic, are we? */
5503 /* Note: In the next call to CreateFile, we use zero as the 2nd
5504 argument because, when the symlink is a hidden/system file,
5505 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5506 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5507 and directory symlinks. */
5508 if (w32_unicode_filenames
)
5510 wchar_t path_w
[MAX_PATH
];
5512 filename_to_utf16 (path
, path_w
);
5513 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5514 FILE_FLAG_OPEN_REPARSE_POINT
5515 | FILE_FLAG_BACKUP_SEMANTICS
,
5520 char path_a
[MAX_PATH
];
5522 filename_to_ansi (path
, path_a
);
5523 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5524 FILE_FLAG_OPEN_REPARSE_POINT
5525 | FILE_FLAG_BACKUP_SEMANTICS
,
5528 if (sh
!= INVALID_HANDLE_VALUE
)
5530 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5531 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5534 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5535 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5538 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5542 /* Copy the link target name, in wide characters, from
5543 reparse_data, then convert it to multibyte encoding in
5544 the current locale's codepage. */
5548 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5550 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5551 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5552 size_t size_to_copy
= buf_size
;
5554 /* According to MSDN, PrintNameLength does not include the
5555 terminating null character. */
5556 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5557 memcpy (lwname
, lwname_src
, lwname_len
);
5558 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5559 filename_from_utf16 (lwname
, resolved
);
5560 dostounix_filename (resolved
);
5561 lname_size
= strlen (resolved
) + 1;
5562 if (lname_size
<= buf_size
)
5563 size_to_copy
= lname_size
;
5564 strncpy (buf
, resolved
, size_to_copy
);
5566 retval
= size_to_copy
;
5572 /* CreateFile failed. */
5573 DWORD w32err2
= GetLastError ();
5577 case ERROR_FILE_NOT_FOUND
:
5578 case ERROR_PATH_NOT_FOUND
:
5581 case ERROR_ACCESS_DENIED
:
5582 case ERROR_TOO_MANY_OPEN_FILES
:
5592 restore_privilege (&privs
);
5600 readlinkat (int fd
, char const *name
, char *buffer
,
5603 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5604 as in fstatat. FIXME: Add proper support for readlinkat. */
5605 char fullname
[MAX_UTF8_PATH
];
5609 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5612 errno
= ENAMETOOLONG
;
5618 return readlink (name
, buffer
, buffer_size
);
5621 /* If FILE is a symlink, return its target (stored in a static
5622 buffer); otherwise return FILE.
5624 This function repeatedly resolves symlinks in the last component of
5625 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5626 until it arrives at a file whose last component is not a symlink,
5627 or some error occurs. It returns the target of the last
5628 successfully resolved symlink in the chain. If it succeeds to
5629 resolve even a single symlink, the value returned is an absolute
5630 file name with backslashes (result of GetFullPathName). By
5631 contrast, if the original FILE is returned, it is unaltered.
5633 Note: This function can set errno even if it succeeds.
5635 Implementation note: we only resolve the last portion ("basename")
5636 of the argument FILE and of each following file in the chain,
5637 disregarding any possible symlinks in its leading directories.
5638 This is because Windows system calls and library functions
5639 transparently resolve symlinks in leading directories and return
5640 correct information, as long as the basename is not a symlink. */
5642 chase_symlinks (const char *file
)
5644 static char target
[MAX_UTF8_PATH
];
5645 char link
[MAX_UTF8_PATH
];
5646 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5647 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5648 ssize_t res
, link_len
;
5651 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5652 return (char *)file
;
5654 if (w32_unicode_filenames
)
5656 wchar_t file_w
[MAX_PATH
];
5658 filename_to_utf16 (file
, file_w
);
5659 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5660 return (char *)file
;
5661 filename_from_utf16 (link_w
, link
);
5665 char file_a
[MAX_PATH
];
5667 filename_to_ansi (file
, file_a
);
5668 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5669 return (char *)file
;
5670 filename_from_ansi (link_a
, link
);
5672 link_len
= strlen (link
);
5677 /* Remove trailing slashes, as we want to resolve the last
5678 non-trivial part of the link name. */
5679 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5680 link
[link_len
--] = '\0';
5682 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5686 if (!(IS_DEVICE_SEP (target
[1])
5687 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5689 /* Target is relative. Append it to the directory part of
5690 the symlink, then copy the result back to target. */
5691 char *p
= link
+ link_len
;
5693 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5696 strcpy (target
, link
);
5698 /* Resolve any "." and ".." to get a fully-qualified file name
5700 if (w32_unicode_filenames
)
5702 filename_to_utf16 (target
, target_w
);
5703 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5705 filename_from_utf16 (link_w
, link
);
5709 filename_to_ansi (target
, target_a
);
5710 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5712 filename_from_ansi (link_a
, link
);
5714 link_len
= strlen (link
);
5716 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5718 if (loop_count
> 100)
5721 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5722 return (char *)file
;
5727 /* Posix ACL emulation. */
5730 acl_valid (acl_t acl
)
5732 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5736 acl_to_text (acl_t acl
, ssize_t
*size
)
5739 SECURITY_INFORMATION flags
=
5740 OWNER_SECURITY_INFORMATION
|
5741 GROUP_SECURITY_INFORMATION
|
5742 DACL_SECURITY_INFORMATION
;
5743 char *retval
= NULL
;
5749 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5752 /* We don't want to mix heaps, so we duplicate the string in our
5753 heap and free the one allocated by the API. */
5754 retval
= xstrdup (str_acl
);
5757 LocalFree (str_acl
);
5759 else if (errno
!= ENOTSUP
)
5766 acl_from_text (const char *acl_str
)
5768 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5774 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5777 retval
= xmalloc (sd_size
);
5778 memcpy (retval
, psd
, sd_size
);
5781 else if (errno
!= ENOTSUP
)
5788 acl_free (void *ptr
)
5795 acl_get_file (const char *fname
, acl_type_t type
)
5797 PSECURITY_DESCRIPTOR psd
= NULL
;
5798 const char *filename
;
5800 if (type
== ACL_TYPE_ACCESS
)
5803 SECURITY_INFORMATION si
=
5804 OWNER_SECURITY_INFORMATION
|
5805 GROUP_SECURITY_INFORMATION
|
5806 DACL_SECURITY_INFORMATION
;
5809 filename
= map_w32_filename (fname
, NULL
);
5810 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5811 fname
= chase_symlinks (filename
);
5816 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5817 && errno
!= ENOTSUP
)
5819 err
= GetLastError ();
5820 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5822 psd
= xmalloc (sd_len
);
5823 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5830 else if (err
== ERROR_FILE_NOT_FOUND
5831 || err
== ERROR_PATH_NOT_FOUND
5832 /* ERROR_INVALID_NAME is what we get if
5833 w32-unicode-filenames is nil and the file cannot
5834 be encoded in the current ANSI codepage. */
5835 || err
== ERROR_INVALID_NAME
)
5843 else if (type
!= ACL_TYPE_DEFAULT
)
5850 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5852 TOKEN_PRIVILEGES old1
, old2
;
5854 int st
= 0, retval
= -1;
5855 SECURITY_INFORMATION flags
= 0;
5861 const char *filename
;
5863 if (acl_valid (acl
) != 0
5864 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5870 if (type
== ACL_TYPE_DEFAULT
)
5876 filename
= map_w32_filename (fname
, NULL
);
5877 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5878 fname
= chase_symlinks (filename
);
5882 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5884 flags
|= OWNER_SECURITY_INFORMATION
;
5885 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5887 flags
|= GROUP_SECURITY_INFORMATION
;
5888 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5891 flags
|= DACL_SECURITY_INFORMATION
;
5895 /* According to KB-245153, setting the owner will succeed if either:
5896 (1) the caller is the user who will be the new owner, and has the
5897 SE_TAKE_OWNERSHIP privilege, or
5898 (2) the caller has the SE_RESTORE privilege, in which case she can
5899 set any valid user or group as the owner
5901 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5902 privileges, and disregard any failures in obtaining them. If
5903 these privileges cannot be obtained, and do not already exist in
5904 the calling thread's security token, this function could fail
5906 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5908 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5913 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5915 err
= GetLastError ();
5917 if (errno
== ENOTSUP
)
5919 else if (err
== ERROR_INVALID_OWNER
5920 || err
== ERROR_NOT_ALL_ASSIGNED
5921 || err
== ERROR_ACCESS_DENIED
)
5923 /* Maybe the requested ACL and the one the file already has
5924 are identical, in which case we can silently ignore the
5925 failure. (And no, Windows doesn't.) */
5926 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5931 char *acl_from
= acl_to_text (current_acl
, NULL
);
5932 char *acl_to
= acl_to_text (acl
, NULL
);
5934 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5940 acl_free (acl_from
);
5943 acl_free (current_acl
);
5946 else if (err
== ERROR_FILE_NOT_FOUND
5947 || err
== ERROR_PATH_NOT_FOUND
5948 /* ERROR_INVALID_NAME is what we get if
5949 w32-unicode-filenames is nil and the file cannot be
5950 encoded in the current ANSI codepage. */
5951 || err
== ERROR_INVALID_NAME
)
5965 restore_privilege (&old2
);
5966 restore_privilege (&old1
);
5974 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5975 have a fixed max size for file names, so we don't need the kind of
5976 alloc/malloc/realloc dance the gnulib version does. We also don't
5977 support FD-relative symlinks. */
5979 careadlinkat (int fd
, char const *filename
,
5980 char *buffer
, size_t buffer_size
,
5981 struct allocator
const *alloc
,
5982 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
5984 char linkname
[MAX_UTF8_PATH
];
5987 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
5991 char *retval
= buffer
;
5993 linkname
[link_size
++] = '\0';
5994 if (link_size
> buffer_size
)
5995 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
5997 memcpy (retval
, linkname
, link_size
);
6005 /* Support for browsing other processes and their attributes. See
6006 process.c for the Lisp bindings. */
6008 /* Helper wrapper functions. */
6010 static HANDLE WINAPI
6011 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6013 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6015 if (g_b_init_create_toolhelp32_snapshot
== 0)
6017 g_b_init_create_toolhelp32_snapshot
= 1;
6018 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6019 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6020 "CreateToolhelp32Snapshot");
6022 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6024 return INVALID_HANDLE_VALUE
;
6026 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6030 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6032 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6034 if (g_b_init_process32_first
== 0)
6036 g_b_init_process32_first
= 1;
6037 s_pfn_Process32_First
= (Process32First_Proc
)
6038 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6041 if (s_pfn_Process32_First
== NULL
)
6045 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6049 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6051 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6053 if (g_b_init_process32_next
== 0)
6055 g_b_init_process32_next
= 1;
6056 s_pfn_Process32_Next
= (Process32Next_Proc
)
6057 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6060 if (s_pfn_Process32_Next
== NULL
)
6064 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6068 open_thread_token (HANDLE ThreadHandle
,
6069 DWORD DesiredAccess
,
6071 PHANDLE TokenHandle
)
6073 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6074 HMODULE hm_advapi32
= NULL
;
6075 if (is_windows_9x () == TRUE
)
6077 SetLastError (ERROR_NOT_SUPPORTED
);
6080 if (g_b_init_open_thread_token
== 0)
6082 g_b_init_open_thread_token
= 1;
6083 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6084 s_pfn_Open_Thread_Token
=
6085 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6087 if (s_pfn_Open_Thread_Token
== NULL
)
6089 SetLastError (ERROR_NOT_SUPPORTED
);
6093 s_pfn_Open_Thread_Token (
6102 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6104 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6105 HMODULE hm_advapi32
= NULL
;
6106 if (is_windows_9x () == TRUE
)
6110 if (g_b_init_impersonate_self
== 0)
6112 g_b_init_impersonate_self
= 1;
6113 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6114 s_pfn_Impersonate_Self
=
6115 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6117 if (s_pfn_Impersonate_Self
== NULL
)
6121 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6125 revert_to_self (void)
6127 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6128 HMODULE hm_advapi32
= NULL
;
6129 if (is_windows_9x () == TRUE
)
6133 if (g_b_init_revert_to_self
== 0)
6135 g_b_init_revert_to_self
= 1;
6136 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6137 s_pfn_Revert_To_Self
=
6138 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6140 if (s_pfn_Revert_To_Self
== NULL
)
6144 return s_pfn_Revert_To_Self ();
6148 get_process_memory_info (HANDLE h_proc
,
6149 PPROCESS_MEMORY_COUNTERS mem_counters
,
6152 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6153 HMODULE hm_psapi
= NULL
;
6154 if (is_windows_9x () == TRUE
)
6158 if (g_b_init_get_process_memory_info
== 0)
6160 g_b_init_get_process_memory_info
= 1;
6161 hm_psapi
= LoadLibrary ("Psapi.dll");
6163 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6164 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6166 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6170 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6174 get_process_working_set_size (HANDLE h_proc
,
6178 static GetProcessWorkingSetSize_Proc
6179 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6181 if (is_windows_9x () == TRUE
)
6185 if (g_b_init_get_process_working_set_size
== 0)
6187 g_b_init_get_process_working_set_size
= 1;
6188 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6189 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6190 "GetProcessWorkingSetSize");
6192 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6196 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6200 global_memory_status (MEMORYSTATUS
*buf
)
6202 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6204 if (is_windows_9x () == TRUE
)
6208 if (g_b_init_global_memory_status
== 0)
6210 g_b_init_global_memory_status
= 1;
6211 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6212 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6213 "GlobalMemoryStatus");
6215 if (s_pfn_Global_Memory_Status
== NULL
)
6219 return s_pfn_Global_Memory_Status (buf
);
6223 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6225 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6227 if (is_windows_9x () == TRUE
)
6231 if (g_b_init_global_memory_status_ex
== 0)
6233 g_b_init_global_memory_status_ex
= 1;
6234 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6235 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6236 "GlobalMemoryStatusEx");
6238 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6242 return s_pfn_Global_Memory_Status_Ex (buf
);
6246 list_system_processes (void)
6248 struct gcpro gcpro1
;
6249 Lisp_Object proclist
= Qnil
;
6252 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6254 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6256 PROCESSENTRY32 proc_entry
;
6262 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6263 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6264 res
= process32_next (h_snapshot
, &proc_entry
))
6266 proc_id
= proc_entry
.th32ProcessID
;
6267 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6270 CloseHandle (h_snapshot
);
6272 proclist
= Fnreverse (proclist
);
6279 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6281 TOKEN_PRIVILEGES priv
;
6282 DWORD priv_size
= sizeof (priv
);
6283 DWORD opriv_size
= sizeof (*old_priv
);
6284 HANDLE h_token
= NULL
;
6285 HANDLE h_thread
= GetCurrentThread ();
6289 res
= open_thread_token (h_thread
,
6290 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6292 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6294 if (impersonate_self (SecurityImpersonation
))
6295 res
= open_thread_token (h_thread
,
6296 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6301 priv
.PrivilegeCount
= 1;
6302 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6303 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6304 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6305 old_priv
, &opriv_size
)
6306 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6310 CloseHandle (h_token
);
6316 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6318 DWORD priv_size
= sizeof (*priv
);
6319 HANDLE h_token
= NULL
;
6322 if (open_thread_token (GetCurrentThread (),
6323 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6326 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6327 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6331 CloseHandle (h_token
);
6337 ltime (ULONGLONG time_100ns
)
6339 ULONGLONG time_sec
= time_100ns
/ 10000000;
6340 int subsec
= time_100ns
% 10000000;
6341 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6342 subsec
/ 10, subsec
% 10 * 100000);
6345 #define U64_TO_LISP_TIME(time) ltime (time)
6348 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6349 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6352 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6353 ULONGLONG tem1
, tem2
, tem3
, tem
;
6356 || !get_process_times_fn
6357 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6358 &ft_kernel
, &ft_user
))
6361 GetSystemTimeAsFileTime (&ft_current
);
6363 FILETIME_TO_U64 (tem1
, ft_kernel
);
6364 *stime
= U64_TO_LISP_TIME (tem1
);
6366 FILETIME_TO_U64 (tem2
, ft_user
);
6367 *utime
= U64_TO_LISP_TIME (tem2
);
6370 *ttime
= U64_TO_LISP_TIME (tem3
);
6372 FILETIME_TO_U64 (tem
, ft_creation
);
6373 /* Process no 4 (System) returns zero creation time. */
6376 *ctime
= U64_TO_LISP_TIME (tem
);
6380 FILETIME_TO_U64 (tem3
, ft_current
);
6381 tem
= (tem3
- utc_base
) - tem
;
6383 *etime
= U64_TO_LISP_TIME (tem
);
6387 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6398 system_process_attributes (Lisp_Object pid
)
6400 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6401 Lisp_Object attrs
= Qnil
;
6402 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6403 HANDLE h_snapshot
, h_proc
;
6406 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6407 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6408 DWORD glength
= sizeof (gname
);
6409 HANDLE token
= NULL
;
6410 SID_NAME_USE user_type
;
6411 unsigned char *buf
= NULL
;
6413 TOKEN_USER user_token
;
6414 TOKEN_PRIMARY_GROUP group_token
;
6417 PROCESS_MEMORY_COUNTERS mem
;
6418 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6419 SIZE_T minrss
, maxrss
;
6421 MEMORY_STATUS_EX memstex
;
6422 double totphys
= 0.0;
6423 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6425 BOOL result
= FALSE
;
6427 CHECK_NUMBER_OR_FLOAT (pid
);
6428 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6430 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6432 GCPRO3 (attrs
, decoded_cmd
, tem
);
6434 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6439 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6440 for (res
= process32_first (h_snapshot
, &pe
); res
;
6441 res
= process32_next (h_snapshot
, &pe
))
6443 if (proc_id
== pe
.th32ProcessID
)
6446 decoded_cmd
= build_string ("Idle");
6449 /* Decode the command name from locale-specific
6451 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6454 code_convert_string_norecord (cmd_str
,
6455 Vlocale_coding_system
, 0);
6457 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6458 attrs
= Fcons (Fcons (Qppid
,
6459 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6461 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6463 attrs
= Fcons (Fcons (Qthcount
,
6464 make_fixnum_or_float (pe
.cntThreads
)),
6471 CloseHandle (h_snapshot
);
6480 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6482 /* If we were denied a handle to the process, try again after
6483 enabling the SeDebugPrivilege in our process. */
6486 TOKEN_PRIVILEGES priv_current
;
6488 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6490 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6492 restore_privilege (&priv_current
);
6498 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6501 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6502 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6504 buf
= xmalloc (blen
);
6505 result
= get_token_information (token
, TokenUser
,
6506 (LPVOID
)buf
, blen
, &needed
);
6509 memcpy (&user_token
, buf
, sizeof (user_token
));
6510 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6512 euid
= get_rid (user_token
.User
.Sid
);
6513 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6518 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6521 strcpy (uname
, "unknown");
6525 ulength
= strlen (uname
);
6531 /* Determine a reasonable euid and gid values. */
6532 if (xstrcasecmp ("administrator", uname
) == 0)
6534 euid
= 500; /* well-known Administrator uid */
6535 egid
= 513; /* well-known None gid */
6539 /* Get group id and name. */
6540 result
= get_token_information (token
, TokenPrimaryGroup
,
6541 (LPVOID
)buf
, blen
, &needed
);
6542 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6544 buf
= xrealloc (buf
, blen
= needed
);
6545 result
= get_token_information (token
, TokenPrimaryGroup
,
6546 (LPVOID
)buf
, blen
, &needed
);
6550 memcpy (&group_token
, buf
, sizeof (group_token
));
6551 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6553 egid
= get_rid (group_token
.PrimaryGroup
);
6554 dlength
= sizeof (domain
);
6556 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6557 gname
, &glength
, NULL
, &dlength
,
6560 w32_add_to_cache (group_token
.PrimaryGroup
,
6564 strcpy (gname
, "None");
6568 glength
= strlen (gname
);
6576 if (!is_windows_9x ())
6578 /* We couldn't open the process token, presumably because of
6579 insufficient access rights. Assume this process is run
6581 strcpy (uname
, "SYSTEM");
6582 strcpy (gname
, "None");
6583 euid
= 18; /* SYSTEM */
6584 egid
= 513; /* None */
6585 glength
= strlen (gname
);
6586 ulength
= strlen (uname
);
6588 /* If we are running under Windows 9X, where security calls are
6589 not supported, we assume all processes are run by the current
6591 else if (GetUserName (uname
, &ulength
))
6593 if (xstrcasecmp ("administrator", uname
) == 0)
6598 strcpy (gname
, "None");
6599 glength
= strlen (gname
);
6600 ulength
= strlen (uname
);
6606 strcpy (uname
, "administrator");
6607 ulength
= strlen (uname
);
6608 strcpy (gname
, "None");
6609 glength
= strlen (gname
);
6612 CloseHandle (token
);
6615 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6616 tem
= make_unibyte_string (uname
, ulength
);
6617 attrs
= Fcons (Fcons (Quser
,
6618 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6620 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6621 tem
= make_unibyte_string (gname
, glength
);
6622 attrs
= Fcons (Fcons (Qgroup
,
6623 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6626 if (global_memory_status_ex (&memstex
))
6627 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6628 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6630 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6631 double, so we need to do this for it... */
6633 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6634 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6635 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6637 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6639 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6640 else if (global_memory_status (&memst
))
6641 totphys
= memst
.dwTotalPhys
/ 1024.0;
6644 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6647 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6649 attrs
= Fcons (Fcons (Qmajflt
,
6650 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6652 attrs
= Fcons (Fcons (Qvsize
,
6653 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6655 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6657 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6660 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6662 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6664 attrs
= Fcons (Fcons (Qmajflt
,
6665 make_fixnum_or_float (mem
.PageFaultCount
)),
6667 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6669 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6672 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6674 DWORD rss
= maxrss
/ 1024;
6676 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6678 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6681 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6683 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6684 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6685 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6686 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6687 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6688 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6691 /* FIXME: Retrieve command line by walking the PEB of the process. */
6694 CloseHandle (h_proc
);
6700 /* Wrappers for winsock functions to map between our file descriptors
6701 and winsock's handles; also set h_errno for convenience.
6703 To allow Emacs to run on systems which don't have winsock support
6704 installed, we dynamically link to winsock on startup if present, and
6705 otherwise provide the minimum necessary functionality
6706 (eg. gethostname). */
6708 /* function pointers for relevant socket functions */
6709 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6710 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6711 int (PASCAL
*pfn_WSAGetLastError
) (void);
6712 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6713 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6714 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6715 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6716 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6717 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6718 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6719 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6720 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6721 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6722 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6723 int (PASCAL
*pfn_WSACleanup
) (void);
6725 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6726 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6727 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6728 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6729 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6730 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6731 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6732 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6733 const char * optval
, int optlen
);
6734 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6735 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6737 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6738 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6739 struct sockaddr
* from
, int * fromlen
);
6740 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6741 const struct sockaddr
* to
, int tolen
);
6743 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6744 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6745 #ifndef HANDLE_FLAG_INHERIT
6746 #define HANDLE_FLAG_INHERIT 1
6750 static int winsock_inuse
;
6755 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6757 release_listen_threads ();
6758 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6759 after WSAStartup returns successfully, but it seems reasonable
6760 to allow unloading winsock anyway in that case. */
6761 if (pfn_WSACleanup () == 0 ||
6762 pfn_WSAGetLastError () == WSAENETDOWN
)
6764 if (FreeLibrary (winsock_lib
))
6773 init_winsock (int load_now
)
6775 WSADATA winsockData
;
6777 if (winsock_lib
!= NULL
)
6780 pfn_SetHandleInformation
6781 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6782 "SetHandleInformation");
6784 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6786 if (winsock_lib
!= NULL
)
6788 /* dynamically link to socket functions */
6790 #define LOAD_PROC(fn) \
6791 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6794 LOAD_PROC (WSAStartup
);
6795 LOAD_PROC (WSASetLastError
);
6796 LOAD_PROC (WSAGetLastError
);
6797 LOAD_PROC (WSAEventSelect
);
6798 LOAD_PROC (WSACreateEvent
);
6799 LOAD_PROC (WSACloseEvent
);
6802 LOAD_PROC (connect
);
6803 LOAD_PROC (ioctlsocket
);
6806 LOAD_PROC (closesocket
);
6807 LOAD_PROC (shutdown
);
6810 LOAD_PROC (inet_addr
);
6811 LOAD_PROC (gethostname
);
6812 LOAD_PROC (gethostbyname
);
6813 LOAD_PROC (getservbyname
);
6814 LOAD_PROC (getpeername
);
6815 LOAD_PROC (WSACleanup
);
6816 LOAD_PROC (setsockopt
);
6818 LOAD_PROC (getsockname
);
6820 LOAD_PROC (recvfrom
);
6824 /* specify version 1.1 of winsock */
6825 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6827 if (winsockData
.wVersion
!= 0x101)
6832 /* Report that winsock exists and is usable, but leave
6833 socket functions disabled. I am assuming that calling
6834 WSAStartup does not require any network interaction,
6835 and in particular does not cause or require a dial-up
6836 connection to be established. */
6839 FreeLibrary (winsock_lib
);
6847 FreeLibrary (winsock_lib
);
6857 /* Function to map winsock error codes to errno codes for those errno
6858 code defined in errno.h (errno values not defined by errno.h are
6859 already in nt/inc/sys/socket.h). */
6866 if (winsock_lib
== NULL
)
6869 wsa_err
= pfn_WSAGetLastError ();
6873 case WSAEACCES
: errno
= EACCES
; break;
6874 case WSAEBADF
: errno
= EBADF
; break;
6875 case WSAEFAULT
: errno
= EFAULT
; break;
6876 case WSAEINTR
: errno
= EINTR
; break;
6877 case WSAEINVAL
: errno
= EINVAL
; break;
6878 case WSAEMFILE
: errno
= EMFILE
; break;
6879 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
6880 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
6881 default: errno
= wsa_err
; break;
6889 if (winsock_lib
!= NULL
)
6890 pfn_WSASetLastError (0);
6893 /* Extend strerror to handle the winsock-specific error codes. */
6897 } _wsa_errlist
[] = {
6898 {WSAEINTR
, "Interrupted function call"},
6899 {WSAEBADF
, "Bad file descriptor"},
6900 {WSAEACCES
, "Permission denied"},
6901 {WSAEFAULT
, "Bad address"},
6902 {WSAEINVAL
, "Invalid argument"},
6903 {WSAEMFILE
, "Too many open files"},
6905 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
6906 {WSAEINPROGRESS
, "Operation now in progress"},
6907 {WSAEALREADY
, "Operation already in progress"},
6908 {WSAENOTSOCK
, "Socket operation on non-socket"},
6909 {WSAEDESTADDRREQ
, "Destination address required"},
6910 {WSAEMSGSIZE
, "Message too long"},
6911 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
6912 {WSAENOPROTOOPT
, "Bad protocol option"},
6913 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
6914 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
6915 {WSAEOPNOTSUPP
, "Operation not supported"},
6916 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
6917 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
6918 {WSAEADDRINUSE
, "Address already in use"},
6919 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
6920 {WSAENETDOWN
, "Network is down"},
6921 {WSAENETUNREACH
, "Network is unreachable"},
6922 {WSAENETRESET
, "Network dropped connection on reset"},
6923 {WSAECONNABORTED
, "Software caused connection abort"},
6924 {WSAECONNRESET
, "Connection reset by peer"},
6925 {WSAENOBUFS
, "No buffer space available"},
6926 {WSAEISCONN
, "Socket is already connected"},
6927 {WSAENOTCONN
, "Socket is not connected"},
6928 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
6929 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
6930 {WSAETIMEDOUT
, "Connection timed out"},
6931 {WSAECONNREFUSED
, "Connection refused"},
6932 {WSAELOOP
, "Network loop"}, /* not sure */
6933 {WSAENAMETOOLONG
, "Name is too long"},
6934 {WSAEHOSTDOWN
, "Host is down"},
6935 {WSAEHOSTUNREACH
, "No route to host"},
6936 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
6937 {WSAEPROCLIM
, "Too many processes"},
6938 {WSAEUSERS
, "Too many users"}, /* not sure */
6939 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
6940 {WSAESTALE
, "Data is stale"}, /* not sure */
6941 {WSAEREMOTE
, "Remote error"}, /* not sure */
6943 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
6944 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
6945 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
6946 {WSAEDISCON
, "Graceful shutdown in progress"},
6948 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
6949 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
6950 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
6951 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
6952 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
6953 {WSASYSCALLFAILURE
, "System call failure"},
6954 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
6955 {WSATYPE_NOT_FOUND
, "Class type not found"},
6956 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
6957 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
6958 {WSAEREFUSED
, "Operation refused"}, /* not sure */
6961 {WSAHOST_NOT_FOUND
, "Host not found"},
6962 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
6963 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
6964 {WSANO_DATA
, "Valid name, no data record of requested type"},
6970 sys_strerror (int error_no
)
6973 static char unknown_msg
[40];
6975 if (error_no
>= 0 && error_no
< sys_nerr
)
6976 return sys_errlist
[error_no
];
6978 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
6979 if (_wsa_errlist
[i
].errnum
== error_no
)
6980 return _wsa_errlist
[i
].msg
;
6982 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
6986 /* [andrewi 3-May-96] I've had conflicting results using both methods,
6987 but I believe the method of keeping the socket handle separate (and
6988 insuring it is not inheritable) is the correct one. */
6990 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
6992 static int socket_to_fd (SOCKET s
);
6995 sys_socket (int af
, int type
, int protocol
)
6999 if (winsock_lib
== NULL
)
7002 return INVALID_SOCKET
;
7007 /* call the real socket function */
7008 s
= pfn_socket (af
, type
, protocol
);
7010 if (s
!= INVALID_SOCKET
)
7011 return socket_to_fd (s
);
7017 /* Convert a SOCKET to a file descriptor. */
7019 socket_to_fd (SOCKET s
)
7024 /* Although under NT 3.5 _open_osfhandle will accept a socket
7025 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7026 that does not work under NT 3.1. However, we can get the same
7027 effect by using a backdoor function to replace an existing
7028 descriptor handle with the one we want. */
7030 /* allocate a file descriptor (with appropriate flags) */
7031 fd
= _open ("NUL:", _O_RDWR
);
7034 /* Make a non-inheritable copy of the socket handle. Note
7035 that it is possible that sockets aren't actually kernel
7036 handles, which appears to be the case on Windows 9x when
7037 the MS Proxy winsock client is installed. */
7039 /* Apparently there is a bug in NT 3.51 with some service
7040 packs, which prevents using DuplicateHandle to make a
7041 socket handle non-inheritable (causes WSACleanup to
7042 hang). The work-around is to use SetHandleInformation
7043 instead if it is available and implemented. */
7044 if (pfn_SetHandleInformation
)
7046 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7050 HANDLE parent
= GetCurrentProcess ();
7051 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7053 if (DuplicateHandle (parent
,
7059 DUPLICATE_SAME_ACCESS
))
7061 /* It is possible that DuplicateHandle succeeds even
7062 though the socket wasn't really a kernel handle,
7063 because a real handle has the same value. So
7064 test whether the new handle really is a socket. */
7065 long nonblocking
= 0;
7066 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7068 pfn_closesocket (s
);
7073 CloseHandle (new_s
);
7078 eassert (fd
< MAXDESC
);
7079 fd_info
[fd
].hnd
= (HANDLE
) s
;
7081 /* set our own internal flags */
7082 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7088 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7090 /* attach child_process to fd_info */
7091 if (fd_info
[ fd
].cp
!= NULL
)
7093 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7097 fd_info
[ fd
].cp
= cp
;
7100 winsock_inuse
++; /* count open sockets */
7108 pfn_closesocket (s
);
7114 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7116 if (winsock_lib
== NULL
)
7119 return SOCKET_ERROR
;
7123 if (fd_info
[s
].flags
& FILE_SOCKET
)
7125 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7126 if (rc
== SOCKET_ERROR
)
7131 return SOCKET_ERROR
;
7135 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7137 if (winsock_lib
== NULL
)
7140 return SOCKET_ERROR
;
7144 if (fd_info
[s
].flags
& FILE_SOCKET
)
7146 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7147 if (rc
== SOCKET_ERROR
)
7152 return SOCKET_ERROR
;
7156 sys_htons (u_short hostshort
)
7158 return (winsock_lib
!= NULL
) ?
7159 pfn_htons (hostshort
) : hostshort
;
7163 sys_ntohs (u_short netshort
)
7165 return (winsock_lib
!= NULL
) ?
7166 pfn_ntohs (netshort
) : netshort
;
7170 sys_inet_addr (const char * cp
)
7172 return (winsock_lib
!= NULL
) ?
7173 pfn_inet_addr (cp
) : INADDR_NONE
;
7177 sys_gethostname (char * name
, int namelen
)
7179 if (winsock_lib
!= NULL
)
7184 retval
= pfn_gethostname (name
, namelen
);
7185 if (retval
== SOCKET_ERROR
)
7190 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7191 return !GetComputerName (name
, (DWORD
*)&namelen
);
7194 return SOCKET_ERROR
;
7198 sys_gethostbyname (const char * name
)
7200 struct hostent
* host
;
7201 int h_err
= h_errno
;
7203 if (winsock_lib
== NULL
)
7205 h_errno
= NO_RECOVERY
;
7211 host
= pfn_gethostbyname (name
);
7223 sys_getservbyname (const char * name
, const char * proto
)
7225 struct servent
* serv
;
7227 if (winsock_lib
== NULL
)
7234 serv
= pfn_getservbyname (name
, proto
);
7241 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7243 if (winsock_lib
== NULL
)
7246 return SOCKET_ERROR
;
7250 if (fd_info
[s
].flags
& FILE_SOCKET
)
7252 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7253 if (rc
== SOCKET_ERROR
)
7258 return SOCKET_ERROR
;
7262 sys_shutdown (int s
, int how
)
7264 if (winsock_lib
== NULL
)
7267 return SOCKET_ERROR
;
7271 if (fd_info
[s
].flags
& FILE_SOCKET
)
7273 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7274 if (rc
== SOCKET_ERROR
)
7279 return SOCKET_ERROR
;
7283 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7285 if (winsock_lib
== NULL
)
7288 return SOCKET_ERROR
;
7292 if (fd_info
[s
].flags
& FILE_SOCKET
)
7294 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7295 (const char *)optval
, optlen
);
7296 if (rc
== SOCKET_ERROR
)
7301 return SOCKET_ERROR
;
7305 sys_listen (int s
, int backlog
)
7307 if (winsock_lib
== NULL
)
7310 return SOCKET_ERROR
;
7314 if (fd_info
[s
].flags
& FILE_SOCKET
)
7316 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7317 if (rc
== SOCKET_ERROR
)
7320 fd_info
[s
].flags
|= FILE_LISTEN
;
7324 return SOCKET_ERROR
;
7328 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7330 if (winsock_lib
== NULL
)
7333 return SOCKET_ERROR
;
7337 if (fd_info
[s
].flags
& FILE_SOCKET
)
7339 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7340 if (rc
== SOCKET_ERROR
)
7345 return SOCKET_ERROR
;
7349 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7351 if (winsock_lib
== NULL
)
7358 if (fd_info
[s
].flags
& FILE_LISTEN
)
7360 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7362 if (t
== INVALID_SOCKET
)
7365 fd
= socket_to_fd (t
);
7369 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7370 ResetEvent (fd_info
[s
].cp
->char_avail
);
7379 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7380 struct sockaddr
* from
, int * fromlen
)
7382 if (winsock_lib
== NULL
)
7385 return SOCKET_ERROR
;
7389 if (fd_info
[s
].flags
& FILE_SOCKET
)
7391 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7392 if (rc
== SOCKET_ERROR
)
7397 return SOCKET_ERROR
;
7401 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7402 const struct sockaddr
* to
, int tolen
)
7404 if (winsock_lib
== NULL
)
7407 return SOCKET_ERROR
;
7411 if (fd_info
[s
].flags
& FILE_SOCKET
)
7413 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7414 if (rc
== SOCKET_ERROR
)
7419 return SOCKET_ERROR
;
7422 /* Windows does not have an fcntl function. Provide an implementation
7423 good enough for Emacs. */
7425 fcntl (int s
, int cmd
, int options
)
7427 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7428 invoked in a context where fd1 is closed and all descriptors less
7429 than fd1 are open, so sys_dup is an adequate implementation. */
7430 if (cmd
== F_DUPFD_CLOEXEC
)
7433 if (winsock_lib
== NULL
)
7440 if (fd_info
[s
].flags
& FILE_SOCKET
)
7442 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7444 unsigned long nblock
= 1;
7445 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7446 if (rc
== SOCKET_ERROR
)
7448 /* Keep track of the fact that we set this to non-blocking. */
7449 fd_info
[s
].flags
|= FILE_NDELAY
;
7455 return SOCKET_ERROR
;
7459 return SOCKET_ERROR
;
7463 /* Shadow main io functions: we need to handle pipes and sockets more
7464 intelligently, and implement non-blocking mode as well. */
7477 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7479 child_process
* cp
= fd_info
[fd
].cp
;
7481 fd_info
[fd
].cp
= NULL
;
7483 if (CHILD_ACTIVE (cp
))
7485 /* if last descriptor to active child_process then cleanup */
7487 for (i
= 0; i
< MAXDESC
; i
++)
7491 if (fd_info
[i
].cp
== cp
)
7496 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7498 if (winsock_lib
== NULL
) emacs_abort ();
7500 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7501 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7503 winsock_inuse
--; /* count open sockets */
7505 /* If the process handle is NULL, it's either a socket
7506 or serial connection, or a subprocess that was
7507 already reaped by reap_subprocess, but whose
7508 resources were not yet freed, because its output was
7509 not fully read yet by the time it was reaped. (This
7510 usually happens with async subprocesses whose output
7511 is being read by Emacs.) Otherwise, this process was
7512 not reaped yet, so we set its FD to a negative value
7513 to make sure sys_select will eventually get to
7514 calling the SIGCHLD handler for it, which will then
7515 invoke waitpid and reap_subprocess. */
7516 if (cp
->procinfo
.hProcess
== NULL
)
7524 if (fd
>= 0 && fd
< MAXDESC
)
7525 fd_info
[fd
].flags
= 0;
7527 /* Note that sockets do not need special treatment here (at least on
7528 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7529 closesocket is equivalent to CloseHandle, which is to be expected
7530 because socket handles are fully fledged kernel handles. */
7542 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7544 /* duplicate our internal info as well */
7545 fd_info
[new_fd
] = fd_info
[fd
];
7551 sys_dup2 (int src
, int dst
)
7555 if (dst
< 0 || dst
>= MAXDESC
)
7561 /* make sure we close the destination first if it's a pipe or socket */
7562 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7565 rc
= _dup2 (src
, dst
);
7568 /* duplicate our internal info as well */
7569 fd_info
[dst
] = fd_info
[src
];
7575 pipe2 (int * phandles
, int pipe2_flags
)
7580 eassert (pipe2_flags
== O_CLOEXEC
);
7582 /* make pipe handles non-inheritable; when we spawn a child, we
7583 replace the relevant handle with an inheritable one. Also put
7584 pipes into binary mode; we will do text mode translation ourselves
7586 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7590 /* Protect against overflow, since Windows can open more handles than
7591 our fd_info array has room for. */
7592 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7594 _close (phandles
[0]);
7595 _close (phandles
[1]);
7601 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7602 fd_info
[phandles
[0]].flags
= flags
;
7604 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7605 fd_info
[phandles
[1]].flags
= flags
;
7612 /* Function to do blocking read of one byte, needed to implement
7613 select. It is only allowed on communication ports, sockets, or
7616 _sys_read_ahead (int fd
)
7621 if (fd
< 0 || fd
>= MAXDESC
)
7622 return STATUS_READ_ERROR
;
7624 cp
= fd_info
[fd
].cp
;
7626 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7627 return STATUS_READ_ERROR
;
7629 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7630 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7632 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7636 cp
->status
= STATUS_READ_IN_PROGRESS
;
7638 if (fd_info
[fd
].flags
& FILE_PIPE
)
7640 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7642 /* Give subprocess time to buffer some more output for us before
7643 reporting that input is available; we need this because Windows 95
7644 connects DOS programs to pipes by making the pipe appear to be
7645 the normal console stdout - as a result most DOS programs will
7646 write to stdout without buffering, ie. one character at a
7647 time. Even some W32 programs do this - "dir" in a command
7648 shell on NT is very slow if we don't do this. */
7651 int wait
= w32_pipe_read_delay
;
7657 /* Yield remainder of our time slice, effectively giving a
7658 temporary priority boost to the child process. */
7662 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7664 HANDLE hnd
= fd_info
[fd
].hnd
;
7665 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7668 /* Configure timeouts for blocking read. */
7669 if (!GetCommTimeouts (hnd
, &ct
))
7671 cp
->status
= STATUS_READ_ERROR
;
7672 return STATUS_READ_ERROR
;
7674 ct
.ReadIntervalTimeout
= 0;
7675 ct
.ReadTotalTimeoutMultiplier
= 0;
7676 ct
.ReadTotalTimeoutConstant
= 0;
7677 if (!SetCommTimeouts (hnd
, &ct
))
7679 cp
->status
= STATUS_READ_ERROR
;
7680 return STATUS_READ_ERROR
;
7683 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7685 if (GetLastError () != ERROR_IO_PENDING
)
7687 cp
->status
= STATUS_READ_ERROR
;
7688 return STATUS_READ_ERROR
;
7690 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7692 cp
->status
= STATUS_READ_ERROR
;
7693 return STATUS_READ_ERROR
;
7697 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7699 unsigned long nblock
= 0;
7700 /* We always want this to block, so temporarily disable NDELAY. */
7701 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7702 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7704 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7706 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7709 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7713 if (rc
== sizeof (char))
7714 cp
->status
= STATUS_READ_SUCCEEDED
;
7716 cp
->status
= STATUS_READ_FAILED
;
7722 _sys_wait_accept (int fd
)
7728 if (fd
< 0 || fd
>= MAXDESC
)
7729 return STATUS_READ_ERROR
;
7731 cp
= fd_info
[fd
].cp
;
7733 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7734 return STATUS_READ_ERROR
;
7736 cp
->status
= STATUS_READ_FAILED
;
7738 hEv
= pfn_WSACreateEvent ();
7739 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7740 if (rc
!= SOCKET_ERROR
)
7743 rc
= WaitForSingleObject (hEv
, 500);
7745 } while (rc
== WAIT_TIMEOUT
7746 && cp
->status
!= STATUS_READ_ERROR
7748 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7749 if (rc
== WAIT_OBJECT_0
)
7750 cp
->status
= STATUS_READ_SUCCEEDED
;
7752 pfn_WSACloseEvent (hEv
);
7758 sys_read (int fd
, char * buffer
, unsigned int count
)
7763 char * orig_buffer
= buffer
;
7771 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7773 child_process
*cp
= fd_info
[fd
].cp
;
7775 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7783 /* re-read CR carried over from last read */
7784 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7786 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7790 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7793 /* presence of a child_process structure means we are operating in
7794 non-blocking mode - otherwise we just call _read directly.
7795 Note that the child_process structure might be missing because
7796 reap_subprocess has been called; in this case the pipe is
7797 already broken, so calling _read on it is okay. */
7800 int current_status
= cp
->status
;
7802 switch (current_status
)
7804 case STATUS_READ_FAILED
:
7805 case STATUS_READ_ERROR
:
7806 /* report normal EOF if nothing in buffer */
7808 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7811 case STATUS_READ_READY
:
7812 case STATUS_READ_IN_PROGRESS
:
7813 DebPrint (("sys_read called when read is in progress\n"));
7814 errno
= EWOULDBLOCK
;
7817 case STATUS_READ_SUCCEEDED
:
7818 /* consume read-ahead char */
7819 *buffer
++ = cp
->chr
;
7822 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7823 ResetEvent (cp
->char_avail
);
7825 case STATUS_READ_ACKNOWLEDGED
:
7829 DebPrint (("sys_read: bad status %d\n", current_status
));
7834 if (fd_info
[fd
].flags
& FILE_PIPE
)
7836 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7837 to_read
= min (waiting
, (DWORD
) count
);
7840 nchars
+= _read (fd
, buffer
, to_read
);
7842 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7844 HANDLE hnd
= fd_info
[fd
].hnd
;
7845 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7851 /* Configure timeouts for non-blocking read. */
7852 if (!GetCommTimeouts (hnd
, &ct
))
7857 ct
.ReadIntervalTimeout
= MAXDWORD
;
7858 ct
.ReadTotalTimeoutMultiplier
= 0;
7859 ct
.ReadTotalTimeoutConstant
= 0;
7860 if (!SetCommTimeouts (hnd
, &ct
))
7866 if (!ResetEvent (ovl
->hEvent
))
7871 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
7873 if (GetLastError () != ERROR_IO_PENDING
)
7878 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7887 else /* FILE_SOCKET */
7889 if (winsock_lib
== NULL
) emacs_abort ();
7891 /* do the equivalent of a non-blocking read */
7892 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
7893 if (waiting
== 0 && nchars
== 0)
7895 errno
= EWOULDBLOCK
;
7901 /* always use binary mode for sockets */
7902 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
7903 if (res
== SOCKET_ERROR
)
7905 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
7906 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
7916 int nread
= _read (fd
, buffer
, count
);
7919 else if (nchars
== 0)
7924 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7925 /* Perform text mode translation if required. */
7926 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7928 nchars
= crlf_to_lf (nchars
, orig_buffer
);
7929 /* If buffer contains only CR, return that. To be absolutely
7930 sure we should attempt to read the next char, but in
7931 practice a CR to be followed by LF would not appear by
7932 itself in the buffer. */
7933 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
7935 fd_info
[fd
].flags
|= FILE_LAST_CR
;
7941 nchars
= _read (fd
, buffer
, count
);
7946 /* From w32xfns.c */
7947 extern HANDLE interrupt_handle
;
7949 /* For now, don't bother with a non-blocking mode */
7951 sys_write (int fd
, const void * buffer
, unsigned int count
)
7961 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7963 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
7969 /* Perform text mode translation if required. */
7970 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7972 char * tmpbuf
= alloca (count
* 2);
7973 unsigned char * src
= (void *)buffer
;
7974 unsigned char * dst
= tmpbuf
;
7979 unsigned char *next
;
7980 /* copy next line or remaining bytes */
7981 next
= _memccpy (dst
, src
, '\n', nbytes
);
7984 /* copied one line ending with '\n' */
7985 int copied
= next
- dst
;
7988 /* insert '\r' before '\n' */
7995 /* copied remaining partial line -> now finished */
8002 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8004 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8005 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8006 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8009 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8011 if (GetLastError () != ERROR_IO_PENDING
)
8016 if (detect_input_pending ())
8017 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8020 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8021 if (active
== WAIT_OBJECT_0
)
8022 { /* User pressed C-g, cancel write, then leave. Don't bother
8023 cleaning up as we may only get stuck in buggy drivers. */
8024 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8029 if (active
== WAIT_OBJECT_0
+ 1
8030 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8037 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8039 unsigned long nblock
= 0;
8040 if (winsock_lib
== NULL
) emacs_abort ();
8042 /* TODO: implement select() properly so non-blocking I/O works. */
8043 /* For now, make sure the write blocks. */
8044 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8045 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8047 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8049 /* Set the socket back to non-blocking if it was before,
8050 for other operations that support it. */
8051 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8054 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8057 if (nchars
== SOCKET_ERROR
)
8059 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8060 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8066 /* Some networked filesystems don't like too large writes, so
8067 break them into smaller chunks. See the Comments section of
8068 the MSDN documentation of WriteFile for details behind the
8069 choice of the value of CHUNK below. See also the thread
8070 http://thread.gmane.org/gmane.comp.version-control.git/145294
8071 in the git mailing list. */
8072 const unsigned char *p
= buffer
;
8073 const unsigned chunk
= 30 * 1024 * 1024;
8078 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8079 int n
= _write (fd
, p
, this_chunk
);
8087 else if (n
< this_chunk
)
8098 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8100 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8102 /* Return information about network interface IFNAME, or about all
8103 interfaces (if IFNAME is nil). */
8105 network_interface_get_info (Lisp_Object ifname
)
8107 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8108 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8109 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8110 Lisp_Object res
= Qnil
;
8112 if (retval
== ERROR_BUFFER_OVERFLOW
)
8114 ainfo
= xrealloc (ainfo
, ainfo_len
);
8115 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8118 if (retval
== ERROR_SUCCESS
)
8120 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8121 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8123 struct sockaddr_in sa
;
8125 /* For the below, we need some winsock functions, so make sure
8126 the winsock DLL is loaded. If we cannot successfully load
8127 it, they will have no use of the information we provide,
8129 if (!winsock_lib
&& !init_winsock (1))
8132 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8134 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8136 /* Present Unix-compatible interface names, instead of the
8137 Windows names, which are really GUIDs not readable by
8139 static const char *ifmt
[] = {
8140 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8155 switch (adapter
->Type
)
8157 case MIB_IF_TYPE_ETHERNET
:
8158 /* Windows before Vista reports wireless adapters as
8159 Ethernet. Work around by looking at the Description
8161 if (strstr (adapter
->Description
, "Wireless "))
8164 if_num
= wlan_count
++;
8168 ifmt_idx
= ETHERNET
;
8169 if_num
= eth_count
++;
8172 case MIB_IF_TYPE_TOKENRING
:
8173 ifmt_idx
= TOKENRING
;
8174 if_num
= tr_count
++;
8176 case MIB_IF_TYPE_FDDI
:
8178 if_num
= fddi_count
++;
8180 case MIB_IF_TYPE_PPP
:
8182 if_num
= ppp_count
++;
8184 case MIB_IF_TYPE_SLIP
:
8186 if_num
= sl_count
++;
8188 case IF_TYPE_IEEE80211
:
8190 if_num
= wlan_count
++;
8192 case MIB_IF_TYPE_LOOPBACK
:
8195 ifmt_idx
= LOOPBACK
;
8196 if_num
= lo_count
++;
8202 ifmt_idx
= OTHER_IF
;
8203 if_num
= ifx_count
++;
8206 if (ifmt_idx
== NONE
)
8208 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8210 sa
.sin_family
= AF_INET
;
8211 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8212 if (ip_addr
== INADDR_NONE
)
8214 /* Bogus address, skip this interface. */
8217 sa
.sin_addr
.s_addr
= ip_addr
;
8220 res
= Fcons (Fcons (build_string (namebuf
),
8221 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8222 sizeof (struct sockaddr
))),
8224 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8226 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8227 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8228 Lisp_Object flags
= Qnil
;
8232 /* Flags. We guess most of them by type, since the
8233 Windows flags are different and hard to get by. */
8234 flags
= Fcons (intern ("up"), flags
);
8235 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8237 flags
= Fcons (intern ("broadcast"), flags
);
8238 flags
= Fcons (intern ("multicast"), flags
);
8240 flags
= Fcons (intern ("running"), flags
);
8241 if (ifmt_idx
== PPP
)
8243 flags
= Fcons (intern ("pointopoint"), flags
);
8244 flags
= Fcons (intern ("noarp"), flags
);
8246 if (adapter
->HaveWins
)
8247 flags
= Fcons (intern ("WINS"), flags
);
8248 if (adapter
->DhcpEnabled
)
8249 flags
= Fcons (intern ("dynamic"), flags
);
8251 res
= Fcons (flags
, res
);
8253 /* Hardware address and its family. */
8254 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8255 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8256 /* Windows does not support AF_LINK or AF_PACKET family
8257 of addresses. Use an arbitrary family number that is
8258 identical to what GNU/Linux returns. */
8259 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8262 sa
.sin_family
= AF_INET
;
8263 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8264 if (net_mask
!= INADDR_NONE
)
8266 sa
.sin_addr
.s_addr
= net_mask
;
8268 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8269 sizeof (struct sockaddr
)),
8273 res
= Fcons (Qnil
, res
);
8275 sa
.sin_family
= AF_INET
;
8276 if (ip_addr
!= INADDR_NONE
)
8278 /* Broadcast address is only reported by
8279 GetAdaptersAddresses, which is of limited
8280 availability. Generate it on our own. */
8281 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8283 sa
.sin_addr
.s_addr
= bcast_addr
;
8285 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8286 sizeof (struct sockaddr
)),
8290 sa
.sin_addr
.s_addr
= ip_addr
;
8292 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8293 sizeof (struct sockaddr
)),
8297 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8300 /* GetAdaptersInfo is documented to not report loopback
8301 interfaces, so we generate one out of thin air. */
8304 sa
.sin_family
= AF_INET
;
8308 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8309 res
= Fcons (Fcons (build_string ("lo"),
8310 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8311 sizeof (struct sockaddr
))),
8314 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8316 res
= Fcons (Fcons (intern ("running"),
8317 Fcons (intern ("loopback"),
8318 Fcons (intern ("up"), Qnil
))), Qnil
);
8319 /* 772 is what 3 different GNU/Linux systems report for
8320 the loopback interface. */
8321 res
= Fcons (Fcons (make_number (772),
8322 Fmake_vector (make_number (6),
8325 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8326 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8327 sizeof (struct sockaddr
)),
8329 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8330 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8331 sizeof (struct sockaddr
)),
8333 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8334 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8335 sizeof (struct sockaddr
)),
8348 network_interface_list (void)
8350 return network_interface_get_info (Qnil
);
8354 network_interface_info (Lisp_Object ifname
)
8356 return network_interface_get_info (ifname
);
8360 /* The Windows CRT functions are "optimized for speed", so they don't
8361 check for timezone and DST changes if they were last called less
8362 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8363 all Emacs features that repeatedly call time functions (e.g.,
8364 display-time) are in real danger of missing timezone and DST
8365 changes. Calling tzset before each localtime call fixes that. */
8367 sys_localtime (const time_t *t
)
8370 return localtime (t
);
8375 /* Try loading LIBRARY_ID from the file(s) specified in
8376 Vdynamic_library_alist. If the library is loaded successfully,
8377 return the handle of the DLL, and record the filename in the
8378 property :loaded-from of LIBRARY_ID. If the library could not be
8379 found, or when it was already loaded (because the handle is not
8380 recorded anywhere, and so is lost after use), return NULL.
8382 We could also save the handle in :loaded-from, but currently
8383 there's no use case for it. */
8385 w32_delayed_load (Lisp_Object library_id
)
8387 HMODULE dll_handle
= NULL
;
8389 CHECK_SYMBOL (library_id
);
8391 if (CONSP (Vdynamic_library_alist
)
8392 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8394 Lisp_Object found
= Qnil
;
8395 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8398 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8400 Lisp_Object dll
= XCAR (dlls
);
8401 char name
[MAX_UTF8_PATH
];
8405 dll
= ENCODE_FILE (dll
);
8406 if (w32_unicode_filenames
)
8408 wchar_t name_w
[MAX_PATH
];
8410 filename_to_utf16 (SSDATA (dll
), name_w
);
8411 dll_handle
= LoadLibraryW (name_w
);
8414 res
= GetModuleFileNameW (dll_handle
, name_w
,
8417 filename_from_utf16 (name_w
, name
);
8422 char name_a
[MAX_PATH
];
8424 filename_to_ansi (SSDATA (dll
), name_a
);
8425 dll_handle
= LoadLibraryA (name_a
);
8428 res
= GetModuleFileNameA (dll_handle
, name_a
,
8431 filename_from_ansi (name_a
, name
);
8436 ptrdiff_t len
= strlen (name
);
8439 /* Possibly truncated */
8440 ? make_specified_string (name
, -1, len
, 1)
8446 Fput (library_id
, QCloaded_from
, found
);
8454 check_windows_init_file (void)
8456 /* A common indication that Emacs is not installed properly is when
8457 it cannot find the Windows installation file. If this file does
8458 not exist in the expected place, tell the user. */
8460 if (!noninteractive
&& !inhibit_window_system
8461 /* Vload_path is not yet initialized when we are loading
8463 && NILP (Vpurify_flag
))
8465 Lisp_Object init_file
;
8468 /* Implementation note: this function runs early during Emacs
8469 startup, before startup.el is run. So Vload_path is still in
8470 its initial unibyte form, but it holds UTF-8 encoded file
8471 names, since init_callproc was already called. So we do not
8472 need to ENCODE_FILE here, but we do need to convert the file
8473 names from UTF-8 to ANSI. */
8474 init_file
= build_string ("term/w32-win");
8475 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
8478 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8479 char *init_file_name
= SDATA (init_file
);
8480 char *load_path
= SDATA (load_path_print
);
8481 char *buffer
= alloca (1024
8482 + strlen (init_file_name
)
8483 + strlen (load_path
));
8488 "The Emacs Windows initialization file \"%s.el\" "
8489 "could not be found in your Emacs installation. "
8490 "Emacs checked the following directories for this file:\n"
8492 "When Emacs cannot find this file, it usually means that it "
8493 "was not installed properly, or its distribution file was "
8494 "not unpacked properly.\nSee the README.W32 file in the "
8495 "top-level Emacs directory for more information.",
8496 init_file_name
, load_path
);
8497 needed
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8501 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8503 MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8505 needed
= WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8506 NULL
, 0, NULL
, NULL
);
8509 char *msg_a
= alloca (needed
+ 1);
8511 WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8518 "Emacs Abort Dialog",
8519 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8520 /* Use the low-level system abort. */
8531 term_ntproc (int ignored
)
8537 /* shutdown the socket interface if necessary */
8544 init_ntproc (int dumping
)
8546 sigset_t initial_mask
= 0;
8548 /* Initialize the socket interface now if available and requested by
8549 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8550 delayed until open-network-stream is called (w32-has-winsock can
8551 also be used to dynamically load or reload winsock).
8553 Conveniently, init_environment is called before us, so
8554 PRELOAD_WINSOCK can be set in the registry. */
8556 /* Always initialize this correctly. */
8559 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8560 init_winsock (TRUE
);
8562 /* Initial preparation for subprocess support: replace our standard
8563 handles with non-inheritable versions. */
8566 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8567 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8568 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8570 parent
= GetCurrentProcess ();
8572 /* ignore errors when duplicating and closing; typically the
8573 handles will be invalid when running as a gui program. */
8574 DuplicateHandle (parent
,
8575 GetStdHandle (STD_INPUT_HANDLE
),
8580 DUPLICATE_SAME_ACCESS
);
8582 DuplicateHandle (parent
,
8583 GetStdHandle (STD_OUTPUT_HANDLE
),
8588 DUPLICATE_SAME_ACCESS
);
8590 DuplicateHandle (parent
,
8591 GetStdHandle (STD_ERROR_HANDLE
),
8596 DUPLICATE_SAME_ACCESS
);
8602 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8603 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8605 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8608 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8609 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8611 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8614 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8615 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8617 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8621 /* unfortunately, atexit depends on implementation of malloc */
8622 /* atexit (term_ntproc); */
8625 /* Make sure we start with all signals unblocked. */
8626 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8627 signal (SIGABRT
, term_ntproc
);
8631 /* determine which drives are fixed, for GetCachedVolumeInformation */
8633 /* GetDriveType must have trailing backslash. */
8634 char drive
[] = "A:\\";
8636 /* Loop over all possible drive letters */
8637 while (*drive
<= 'Z')
8639 /* Record if this drive letter refers to a fixed drive. */
8640 fixed_drives
[DRIVE_INDEX (*drive
)] =
8641 (GetDriveType (drive
) == DRIVE_FIXED
);
8646 /* Reset the volume info cache. */
8647 volume_cache
= NULL
;
8652 shutdown_handler ensures that buffers' autosave files are
8653 up to date when the user logs off, or the system shuts down.
8656 shutdown_handler (DWORD type
)
8658 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8659 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8660 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8661 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8663 /* Shut down cleanly, making sure autosave files are up to date. */
8664 shut_down_emacs (0, Qnil
);
8667 /* Allow other handlers to handle this signal. */
8672 globals_of_w32 is used to initialize those global variables that
8673 must always be initialized on startup even when the global variable
8674 initialized is non zero (see the function main in emacs.c).
8677 globals_of_w32 (void)
8679 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8681 get_process_times_fn
= (GetProcessTimes_Proc
)
8682 GetProcAddress (kernel32
, "GetProcessTimes");
8684 DEFSYM (QCloaded_from
, ":loaded-from");
8686 g_b_init_is_windows_9x
= 0;
8687 g_b_init_open_process_token
= 0;
8688 g_b_init_get_token_information
= 0;
8689 g_b_init_lookup_account_sid
= 0;
8690 g_b_init_get_sid_sub_authority
= 0;
8691 g_b_init_get_sid_sub_authority_count
= 0;
8692 g_b_init_get_security_info
= 0;
8693 g_b_init_get_file_security_w
= 0;
8694 g_b_init_get_file_security_a
= 0;
8695 g_b_init_get_security_descriptor_owner
= 0;
8696 g_b_init_get_security_descriptor_group
= 0;
8697 g_b_init_is_valid_sid
= 0;
8698 g_b_init_create_toolhelp32_snapshot
= 0;
8699 g_b_init_process32_first
= 0;
8700 g_b_init_process32_next
= 0;
8701 g_b_init_open_thread_token
= 0;
8702 g_b_init_impersonate_self
= 0;
8703 g_b_init_revert_to_self
= 0;
8704 g_b_init_get_process_memory_info
= 0;
8705 g_b_init_get_process_working_set_size
= 0;
8706 g_b_init_global_memory_status
= 0;
8707 g_b_init_global_memory_status_ex
= 0;
8708 g_b_init_equal_sid
= 0;
8709 g_b_init_copy_sid
= 0;
8710 g_b_init_get_length_sid
= 0;
8711 g_b_init_get_native_system_info
= 0;
8712 g_b_init_get_system_times
= 0;
8713 g_b_init_create_symbolic_link_w
= 0;
8714 g_b_init_create_symbolic_link_a
= 0;
8715 g_b_init_get_security_descriptor_dacl
= 0;
8716 g_b_init_convert_sd_to_sddl
= 0;
8717 g_b_init_convert_sddl_to_sd
= 0;
8718 g_b_init_is_valid_security_descriptor
= 0;
8719 g_b_init_set_file_security_w
= 0;
8720 g_b_init_set_file_security_a
= 0;
8721 g_b_init_get_adapters_info
= 0;
8722 num_of_processors
= 0;
8723 /* The following sets a handler for shutdown notifications for
8724 console apps. This actually applies to Emacs in both console and
8725 GUI modes, since we had to fool windows into thinking emacs is a
8726 console application to get console mode to work. */
8727 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8729 /* "None" is the default group name on standalone workstations. */
8730 strcpy (dflt_group_name
, "None");
8732 /* Reset, in case it has some value inherited from dump time. */
8733 w32_stat_get_owner_group
= 0;
8735 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8736 (a.k.a. "wide") APIs to invoke functions that accept file
8738 if (is_windows_9x ())
8739 w32_unicode_filenames
= 0;
8741 w32_unicode_filenames
= 1;
8744 /* For make-serial-process */
8746 serial_open (Lisp_Object port_obj
)
8748 char *port
= SSDATA (port_obj
);
8753 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8754 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8755 if (hnd
== INVALID_HANDLE_VALUE
)
8756 error ("Could not open %s", port
);
8757 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8759 error ("Could not open %s", port
);
8763 error ("Could not create child process");
8765 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8766 fd_info
[ fd
].hnd
= hnd
;
8767 fd_info
[ fd
].flags
|=
8768 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8769 if (fd_info
[ fd
].cp
!= NULL
)
8771 error ("fd_info[fd = %d] is already in use", fd
);
8773 fd_info
[ fd
].cp
= cp
;
8774 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8775 if (cp
->ovl_read
.hEvent
== NULL
)
8776 error ("Could not create read event");
8777 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8778 if (cp
->ovl_write
.hEvent
== NULL
)
8779 error ("Could not create write event");
8784 /* For serial-process-configure */
8786 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8788 Lisp_Object childp2
= Qnil
;
8789 Lisp_Object tem
= Qnil
;
8793 char summary
[4] = "???"; /* This usually becomes "8N1". */
8795 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8796 error ("Not a serial process");
8797 hnd
= fd_info
[ p
->outfd
].hnd
;
8799 childp2
= Fcopy_sequence (p
->childp
);
8801 /* Initialize timeouts for blocking read and blocking write. */
8802 if (!GetCommTimeouts (hnd
, &ct
))
8803 error ("GetCommTimeouts() failed");
8804 ct
.ReadIntervalTimeout
= 0;
8805 ct
.ReadTotalTimeoutMultiplier
= 0;
8806 ct
.ReadTotalTimeoutConstant
= 0;
8807 ct
.WriteTotalTimeoutMultiplier
= 0;
8808 ct
.WriteTotalTimeoutConstant
= 0;
8809 if (!SetCommTimeouts (hnd
, &ct
))
8810 error ("SetCommTimeouts() failed");
8811 /* Read port attributes and prepare default configuration. */
8812 memset (&dcb
, 0, sizeof (dcb
));
8813 dcb
.DCBlength
= sizeof (DCB
);
8814 if (!GetCommState (hnd
, &dcb
))
8815 error ("GetCommState() failed");
8818 dcb
.fAbortOnError
= FALSE
;
8819 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8824 /* Configure speed. */
8825 if (!NILP (Fplist_member (contact
, QCspeed
)))
8826 tem
= Fplist_get (contact
, QCspeed
);
8828 tem
= Fplist_get (p
->childp
, QCspeed
);
8830 dcb
.BaudRate
= XINT (tem
);
8831 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8833 /* Configure bytesize. */
8834 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8835 tem
= Fplist_get (contact
, QCbytesize
);
8837 tem
= Fplist_get (p
->childp
, QCbytesize
);
8839 tem
= make_number (8);
8841 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8842 error (":bytesize must be nil (8), 7, or 8");
8843 dcb
.ByteSize
= XINT (tem
);
8844 summary
[0] = XINT (tem
) + '0';
8845 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8847 /* Configure parity. */
8848 if (!NILP (Fplist_member (contact
, QCparity
)))
8849 tem
= Fplist_get (contact
, QCparity
);
8851 tem
= Fplist_get (p
->childp
, QCparity
);
8852 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8853 error (":parity must be nil (no parity), `even', or `odd'");
8854 dcb
.fParity
= FALSE
;
8855 dcb
.Parity
= NOPARITY
;
8856 dcb
.fErrorChar
= FALSE
;
8861 else if (EQ (tem
, Qeven
))
8865 dcb
.Parity
= EVENPARITY
;
8866 dcb
.fErrorChar
= TRUE
;
8868 else if (EQ (tem
, Qodd
))
8872 dcb
.Parity
= ODDPARITY
;
8873 dcb
.fErrorChar
= TRUE
;
8875 childp2
= Fplist_put (childp2
, QCparity
, tem
);
8877 /* Configure stopbits. */
8878 if (!NILP (Fplist_member (contact
, QCstopbits
)))
8879 tem
= Fplist_get (contact
, QCstopbits
);
8881 tem
= Fplist_get (p
->childp
, QCstopbits
);
8883 tem
= make_number (1);
8885 if (XINT (tem
) != 1 && XINT (tem
) != 2)
8886 error (":stopbits must be nil (1 stopbit), 1, or 2");
8887 summary
[2] = XINT (tem
) + '0';
8888 if (XINT (tem
) == 1)
8889 dcb
.StopBits
= ONESTOPBIT
;
8890 else if (XINT (tem
) == 2)
8891 dcb
.StopBits
= TWOSTOPBITS
;
8892 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
8894 /* Configure flowcontrol. */
8895 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
8896 tem
= Fplist_get (contact
, QCflowcontrol
);
8898 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
8899 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
8900 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
8901 dcb
.fOutxCtsFlow
= FALSE
;
8902 dcb
.fOutxDsrFlow
= FALSE
;
8903 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
8904 dcb
.fDsrSensitivity
= FALSE
;
8905 dcb
.fTXContinueOnXoff
= FALSE
;
8908 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
8909 dcb
.XonChar
= 17; /* Control-Q */
8910 dcb
.XoffChar
= 19; /* Control-S */
8913 /* Already configured. */
8915 else if (EQ (tem
, Qhw
))
8917 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
8918 dcb
.fOutxCtsFlow
= TRUE
;
8920 else if (EQ (tem
, Qsw
))
8925 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
8927 /* Activate configuration. */
8928 if (!SetCommState (hnd
, &dcb
))
8929 error ("SetCommState() failed");
8931 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
8932 pset_childp (p
, childp2
);
8938 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
8942 struct timespec timeout
;
8943 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8944 int fd
= process
->infd
;
8946 n
= sys_read (fd
, (char*)buf
, sz
);
8953 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8954 if (err
== EWOULDBLOCK
)
8957 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
8963 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
8965 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8966 int fd
= process
->outfd
;
8967 ssize_t n
= sys_write (fd
, buf
, sz
);
8969 /* 0 or more bytes written means everything went fine. */
8973 /* Negative bytes written means we got an error in errno.
8974 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8975 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
8976 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
8980 #endif /* HAVE_GNUTLS */