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 extern 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
;
277 static BOOL g_b_init_get_security_descriptor_owner
;
278 static BOOL g_b_init_get_security_descriptor_group
;
279 static BOOL g_b_init_is_valid_sid
;
280 static BOOL g_b_init_create_toolhelp32_snapshot
;
281 static BOOL g_b_init_process32_first
;
282 static BOOL g_b_init_process32_next
;
283 static BOOL g_b_init_open_thread_token
;
284 static BOOL g_b_init_impersonate_self
;
285 static BOOL g_b_init_revert_to_self
;
286 static BOOL g_b_init_get_process_memory_info
;
287 static BOOL g_b_init_get_process_working_set_size
;
288 static BOOL g_b_init_global_memory_status
;
289 static BOOL g_b_init_global_memory_status_ex
;
290 static BOOL g_b_init_get_length_sid
;
291 static BOOL g_b_init_equal_sid
;
292 static BOOL g_b_init_copy_sid
;
293 static BOOL g_b_init_get_native_system_info
;
294 static BOOL g_b_init_get_system_times
;
295 static BOOL g_b_init_create_symbolic_link
;
296 static BOOL g_b_init_get_security_descriptor_dacl
;
297 static BOOL g_b_init_convert_sd_to_sddl
;
298 static BOOL g_b_init_convert_sddl_to_sd
;
299 static BOOL g_b_init_is_valid_security_descriptor
;
300 static BOOL g_b_init_set_file_security
;
301 static BOOL g_b_init_get_adapters_info
;
303 int w32_unicode_filenames
;
306 BEGIN: Wrapper functions around OpenProcessToken
307 and other functions in advapi32.dll that are only
308 supported in Windows NT / 2k / XP
310 /* ** Function pointer typedefs ** */
311 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
312 HANDLE ProcessHandle
,
314 PHANDLE TokenHandle
);
315 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
317 TOKEN_INFORMATION_CLASS TokenInformationClass
,
318 LPVOID TokenInformation
,
319 DWORD TokenInformationLength
,
320 PDWORD ReturnLength
);
321 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
322 HANDLE process_handle
,
323 LPFILETIME creation_time
,
324 LPFILETIME exit_time
,
325 LPFILETIME kernel_time
,
326 LPFILETIME user_time
);
328 GetProcessTimes_Proc get_process_times_fn
= NULL
;
331 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
332 const char * const GetFileSecurity_Name
= "GetFileSecurityW";
333 const char * const SetFileSecurity_Name
= "SetFileSecurityW";
335 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
336 const char * const GetFileSecurity_Name
= "GetFileSecurityA";
337 const char * const SetFileSecurity_Name
= "SetFileSecurityA";
339 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
340 LPCTSTR lpSystemName
,
345 LPDWORD cbDomainName
,
346 PSID_NAME_USE peUse
);
347 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
350 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
352 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
354 SE_OBJECT_TYPE ObjectType
,
355 SECURITY_INFORMATION SecurityInfo
,
360 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
361 typedef BOOL (WINAPI
* GetFileSecurity_Proc
) (
363 SECURITY_INFORMATION RequestedInformation
,
364 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
366 LPDWORD lpnLengthNeeded
);
367 typedef BOOL (WINAPI
*SetFileSecurity_Proc
) (
369 SECURITY_INFORMATION SecurityInformation
,
370 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
371 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
372 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
374 LPBOOL lpbOwnerDefaulted
);
375 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
376 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
378 LPBOOL lpbGroupDefaulted
);
379 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
380 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
381 LPBOOL lpbDaclPresent
,
383 LPBOOL lpbDaclDefaulted
);
384 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
386 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
388 DWORD th32ProcessID
);
389 typedef BOOL (WINAPI
* Process32First_Proc
) (
391 LPPROCESSENTRY32 lppe
);
392 typedef BOOL (WINAPI
* Process32Next_Proc
) (
394 LPPROCESSENTRY32 lppe
);
395 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
399 PHANDLE TokenHandle
);
400 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
401 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
402 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
403 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
405 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
407 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
409 PSIZE_T lpMinimumWorkingSetSize
,
410 PSIZE_T lpMaximumWorkingSetSize
);
411 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
412 LPMEMORYSTATUS lpBuffer
);
413 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
414 LPMEMORY_STATUS_EX lpBuffer
);
415 typedef BOOL (WINAPI
* CopySid_Proc
) (
416 DWORD nDestinationSidLength
,
417 PSID pDestinationSid
,
419 typedef BOOL (WINAPI
* EqualSid_Proc
) (
422 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
424 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
425 LPSYSTEM_INFO lpSystemInfo
);
426 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
427 LPFILETIME lpIdleTime
,
428 LPFILETIME lpKernelTime
,
429 LPFILETIME lpUserTime
);
430 typedef BOOLEAN (WINAPI
*CreateSymbolicLink_Proc
) (
431 LPTSTR lpSymlinkFileName
,
432 LPTSTR lpTargetFileName
,
434 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
435 LPCTSTR StringSecurityDescriptor
,
436 DWORD StringSDRevision
,
437 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
438 PULONG SecurityDescriptorSize
);
439 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
440 PSECURITY_DESCRIPTOR SecurityDescriptor
,
441 DWORD RequestedStringSDRevision
,
442 SECURITY_INFORMATION SecurityInformation
,
443 LPTSTR
*StringSecurityDescriptor
,
444 PULONG StringSecurityDescriptorLen
);
445 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
446 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
447 PIP_ADAPTER_INFO pAdapterInfo
,
450 /* ** A utility function ** */
454 static BOOL s_b_ret
= 0;
455 OSVERSIONINFO os_ver
;
456 if (g_b_init_is_windows_9x
== 0)
458 g_b_init_is_windows_9x
= 1;
459 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
460 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
461 if (GetVersionEx (&os_ver
))
463 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
469 static Lisp_Object
ltime (ULONGLONG
);
471 /* Get total user and system times for get-internal-run-time.
472 Returns a list of integers if the times are provided by the OS
473 (NT derivatives), otherwise it returns the result of current-time. */
475 w32_get_internal_run_time (void)
477 if (get_process_times_fn
)
479 FILETIME create
, exit
, kernel
, user
;
480 HANDLE proc
= GetCurrentProcess ();
481 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
483 LARGE_INTEGER user_int
, kernel_int
, total
;
484 user_int
.LowPart
= user
.dwLowDateTime
;
485 user_int
.HighPart
= user
.dwHighDateTime
;
486 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
487 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
488 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
489 return ltime (total
.QuadPart
);
493 return Fcurrent_time ();
496 /* ** The wrapper functions ** */
499 open_process_token (HANDLE ProcessHandle
,
503 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
504 HMODULE hm_advapi32
= NULL
;
505 if (is_windows_9x () == TRUE
)
509 if (g_b_init_open_process_token
== 0)
511 g_b_init_open_process_token
= 1;
512 hm_advapi32
= LoadLibrary ("Advapi32.dll");
513 s_pfn_Open_Process_Token
=
514 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
516 if (s_pfn_Open_Process_Token
== NULL
)
521 s_pfn_Open_Process_Token (
529 get_token_information (HANDLE TokenHandle
,
530 TOKEN_INFORMATION_CLASS TokenInformationClass
,
531 LPVOID TokenInformation
,
532 DWORD TokenInformationLength
,
535 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
536 HMODULE hm_advapi32
= NULL
;
537 if (is_windows_9x () == TRUE
)
541 if (g_b_init_get_token_information
== 0)
543 g_b_init_get_token_information
= 1;
544 hm_advapi32
= LoadLibrary ("Advapi32.dll");
545 s_pfn_Get_Token_Information
=
546 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
548 if (s_pfn_Get_Token_Information
== NULL
)
553 s_pfn_Get_Token_Information (
555 TokenInformationClass
,
557 TokenInformationLength
,
563 lookup_account_sid (LPCTSTR lpSystemName
,
568 LPDWORD cbDomainName
,
571 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
572 HMODULE hm_advapi32
= NULL
;
573 if (is_windows_9x () == TRUE
)
577 if (g_b_init_lookup_account_sid
== 0)
579 g_b_init_lookup_account_sid
= 1;
580 hm_advapi32
= LoadLibrary ("Advapi32.dll");
581 s_pfn_Lookup_Account_Sid
=
582 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
584 if (s_pfn_Lookup_Account_Sid
== NULL
)
589 s_pfn_Lookup_Account_Sid (
601 get_sid_sub_authority (PSID pSid
, DWORD n
)
603 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
604 static DWORD zero
= 0U;
605 HMODULE hm_advapi32
= NULL
;
606 if (is_windows_9x () == TRUE
)
610 if (g_b_init_get_sid_sub_authority
== 0)
612 g_b_init_get_sid_sub_authority
= 1;
613 hm_advapi32
= LoadLibrary ("Advapi32.dll");
614 s_pfn_Get_Sid_Sub_Authority
=
615 (GetSidSubAuthority_Proc
) GetProcAddress (
616 hm_advapi32
, "GetSidSubAuthority");
618 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
622 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
626 get_sid_sub_authority_count (PSID pSid
)
628 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
629 static UCHAR zero
= 0U;
630 HMODULE hm_advapi32
= NULL
;
631 if (is_windows_9x () == TRUE
)
635 if (g_b_init_get_sid_sub_authority_count
== 0)
637 g_b_init_get_sid_sub_authority_count
= 1;
638 hm_advapi32
= LoadLibrary ("Advapi32.dll");
639 s_pfn_Get_Sid_Sub_Authority_Count
=
640 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
641 hm_advapi32
, "GetSidSubAuthorityCount");
643 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
647 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
651 get_security_info (HANDLE handle
,
652 SE_OBJECT_TYPE ObjectType
,
653 SECURITY_INFORMATION SecurityInfo
,
658 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
660 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
661 HMODULE hm_advapi32
= NULL
;
662 if (is_windows_9x () == TRUE
)
666 if (g_b_init_get_security_info
== 0)
668 g_b_init_get_security_info
= 1;
669 hm_advapi32
= LoadLibrary ("Advapi32.dll");
670 s_pfn_Get_Security_Info
=
671 (GetSecurityInfo_Proc
) GetProcAddress (
672 hm_advapi32
, "GetSecurityInfo");
674 if (s_pfn_Get_Security_Info
== NULL
)
678 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
679 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
680 ppSecurityDescriptor
));
684 get_file_security (LPCTSTR lpFileName
,
685 SECURITY_INFORMATION RequestedInformation
,
686 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
688 LPDWORD lpnLengthNeeded
)
690 static GetFileSecurity_Proc s_pfn_Get_File_Security
= NULL
;
691 HMODULE hm_advapi32
= NULL
;
692 if (is_windows_9x () == TRUE
)
697 if (g_b_init_get_file_security
== 0)
699 g_b_init_get_file_security
= 1;
700 hm_advapi32
= LoadLibrary ("Advapi32.dll");
701 s_pfn_Get_File_Security
=
702 (GetFileSecurity_Proc
) GetProcAddress (
703 hm_advapi32
, GetFileSecurity_Name
);
705 if (s_pfn_Get_File_Security
== NULL
)
710 return (s_pfn_Get_File_Security (lpFileName
, RequestedInformation
,
711 pSecurityDescriptor
, nLength
,
716 set_file_security (LPCTSTR lpFileName
,
717 SECURITY_INFORMATION SecurityInformation
,
718 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
720 static SetFileSecurity_Proc s_pfn_Set_File_Security
= NULL
;
721 HMODULE hm_advapi32
= NULL
;
722 if (is_windows_9x () == TRUE
)
727 if (g_b_init_set_file_security
== 0)
729 g_b_init_set_file_security
= 1;
730 hm_advapi32
= LoadLibrary ("Advapi32.dll");
731 s_pfn_Set_File_Security
=
732 (SetFileSecurity_Proc
) GetProcAddress (
733 hm_advapi32
, SetFileSecurity_Name
);
735 if (s_pfn_Set_File_Security
== NULL
)
740 return (s_pfn_Set_File_Security (lpFileName
, SecurityInformation
,
741 pSecurityDescriptor
));
745 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
747 LPBOOL lpbOwnerDefaulted
)
749 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
750 HMODULE hm_advapi32
= NULL
;
751 if (is_windows_9x () == TRUE
)
756 if (g_b_init_get_security_descriptor_owner
== 0)
758 g_b_init_get_security_descriptor_owner
= 1;
759 hm_advapi32
= LoadLibrary ("Advapi32.dll");
760 s_pfn_Get_Security_Descriptor_Owner
=
761 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
762 hm_advapi32
, "GetSecurityDescriptorOwner");
764 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
769 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
774 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
776 LPBOOL lpbGroupDefaulted
)
778 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
779 HMODULE hm_advapi32
= NULL
;
780 if (is_windows_9x () == TRUE
)
785 if (g_b_init_get_security_descriptor_group
== 0)
787 g_b_init_get_security_descriptor_group
= 1;
788 hm_advapi32
= LoadLibrary ("Advapi32.dll");
789 s_pfn_Get_Security_Descriptor_Group
=
790 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
791 hm_advapi32
, "GetSecurityDescriptorGroup");
793 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
798 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
803 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
804 LPBOOL lpbDaclPresent
,
806 LPBOOL lpbDaclDefaulted
)
808 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
809 HMODULE hm_advapi32
= NULL
;
810 if (is_windows_9x () == TRUE
)
815 if (g_b_init_get_security_descriptor_dacl
== 0)
817 g_b_init_get_security_descriptor_dacl
= 1;
818 hm_advapi32
= LoadLibrary ("Advapi32.dll");
819 s_pfn_Get_Security_Descriptor_Dacl
=
820 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
821 hm_advapi32
, "GetSecurityDescriptorDacl");
823 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
828 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
829 lpbDaclPresent
, pDacl
,
834 is_valid_sid (PSID sid
)
836 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
837 HMODULE hm_advapi32
= NULL
;
838 if (is_windows_9x () == TRUE
)
842 if (g_b_init_is_valid_sid
== 0)
844 g_b_init_is_valid_sid
= 1;
845 hm_advapi32
= LoadLibrary ("Advapi32.dll");
847 (IsValidSid_Proc
) GetProcAddress (
848 hm_advapi32
, "IsValidSid");
850 if (s_pfn_Is_Valid_Sid
== NULL
)
854 return (s_pfn_Is_Valid_Sid (sid
));
858 equal_sid (PSID sid1
, PSID sid2
)
860 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
861 HMODULE hm_advapi32
= NULL
;
862 if (is_windows_9x () == TRUE
)
866 if (g_b_init_equal_sid
== 0)
868 g_b_init_equal_sid
= 1;
869 hm_advapi32
= LoadLibrary ("Advapi32.dll");
871 (EqualSid_Proc
) GetProcAddress (
872 hm_advapi32
, "EqualSid");
874 if (s_pfn_Equal_Sid
== NULL
)
878 return (s_pfn_Equal_Sid (sid1
, sid2
));
882 get_length_sid (PSID sid
)
884 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
885 HMODULE hm_advapi32
= NULL
;
886 if (is_windows_9x () == TRUE
)
890 if (g_b_init_get_length_sid
== 0)
892 g_b_init_get_length_sid
= 1;
893 hm_advapi32
= LoadLibrary ("Advapi32.dll");
894 s_pfn_Get_Length_Sid
=
895 (GetLengthSid_Proc
) GetProcAddress (
896 hm_advapi32
, "GetLengthSid");
898 if (s_pfn_Get_Length_Sid
== NULL
)
902 return (s_pfn_Get_Length_Sid (sid
));
906 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
908 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
909 HMODULE hm_advapi32
= NULL
;
910 if (is_windows_9x () == TRUE
)
914 if (g_b_init_copy_sid
== 0)
916 g_b_init_copy_sid
= 1;
917 hm_advapi32
= LoadLibrary ("Advapi32.dll");
919 (CopySid_Proc
) GetProcAddress (
920 hm_advapi32
, "CopySid");
922 if (s_pfn_Copy_Sid
== NULL
)
926 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
930 END: Wrapper functions around OpenProcessToken
931 and other functions in advapi32.dll that are only
932 supported in Windows NT / 2k / XP
936 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
938 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
939 if (is_windows_9x () != TRUE
)
941 if (g_b_init_get_native_system_info
== 0)
943 g_b_init_get_native_system_info
= 1;
944 s_pfn_Get_Native_System_Info
=
945 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
946 "GetNativeSystemInfo");
948 if (s_pfn_Get_Native_System_Info
!= NULL
)
949 s_pfn_Get_Native_System_Info (lpSystemInfo
);
952 lpSystemInfo
->dwNumberOfProcessors
= -1;
956 get_system_times (LPFILETIME lpIdleTime
,
957 LPFILETIME lpKernelTime
,
958 LPFILETIME lpUserTime
)
960 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
961 if (is_windows_9x () == TRUE
)
965 if (g_b_init_get_system_times
== 0)
967 g_b_init_get_system_times
= 1;
968 s_pfn_Get_System_times
=
969 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
972 if (s_pfn_Get_System_times
== NULL
)
974 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
977 static BOOLEAN WINAPI
978 create_symbolic_link (LPTSTR lpSymlinkFilename
,
979 LPTSTR lpTargetFileName
,
982 static CreateSymbolicLink_Proc s_pfn_Create_Symbolic_Link
= NULL
;
985 if (is_windows_9x () == TRUE
)
990 if (g_b_init_create_symbolic_link
== 0)
992 g_b_init_create_symbolic_link
= 1;
994 s_pfn_Create_Symbolic_Link
=
995 (CreateSymbolicLink_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
996 "CreateSymbolicLinkW");
998 s_pfn_Create_Symbolic_Link
=
999 (CreateSymbolicLink_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1000 "CreateSymbolicLinkA");
1003 if (s_pfn_Create_Symbolic_Link
== NULL
)
1009 retval
= s_pfn_Create_Symbolic_Link (lpSymlinkFilename
, lpTargetFileName
,
1011 /* If we were denied creation of the symlink, try again after
1012 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1015 TOKEN_PRIVILEGES priv_current
;
1017 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
, &priv_current
))
1019 retval
= s_pfn_Create_Symbolic_Link (lpSymlinkFilename
, lpTargetFileName
,
1021 restore_privilege (&priv_current
);
1029 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1031 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1033 if (is_windows_9x () == TRUE
)
1039 if (g_b_init_is_valid_security_descriptor
== 0)
1041 g_b_init_is_valid_security_descriptor
= 1;
1042 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1043 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1044 "IsValidSecurityDescriptor");
1046 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1052 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1056 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1057 DWORD RequestedStringSDRevision
,
1058 SECURITY_INFORMATION SecurityInformation
,
1059 LPTSTR
*StringSecurityDescriptor
,
1060 PULONG StringSecurityDescriptorLen
)
1062 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1065 if (is_windows_9x () == TRUE
)
1071 if (g_b_init_convert_sd_to_sddl
== 0)
1073 g_b_init_convert_sd_to_sddl
= 1;
1075 s_pfn_Convert_SD_To_SDDL
=
1076 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1077 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1079 s_pfn_Convert_SD_To_SDDL
=
1080 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1081 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1084 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1090 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1091 RequestedStringSDRevision
,
1092 SecurityInformation
,
1093 StringSecurityDescriptor
,
1094 StringSecurityDescriptorLen
);
1100 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1101 DWORD StringSDRevision
,
1102 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1103 PULONG SecurityDescriptorSize
)
1105 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1108 if (is_windows_9x () == TRUE
)
1114 if (g_b_init_convert_sddl_to_sd
== 0)
1116 g_b_init_convert_sddl_to_sd
= 1;
1118 s_pfn_Convert_SDDL_To_SD
=
1119 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1120 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1122 s_pfn_Convert_SDDL_To_SD
=
1123 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1124 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1127 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1133 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1136 SecurityDescriptorSize
);
1142 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1144 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1145 HMODULE hm_iphlpapi
= NULL
;
1147 if (is_windows_9x () == TRUE
)
1148 return ERROR_NOT_SUPPORTED
;
1150 if (g_b_init_get_adapters_info
== 0)
1152 g_b_init_get_adapters_info
= 1;
1153 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1155 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1156 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1158 if (s_pfn_Get_Adapters_Info
== NULL
)
1159 return ERROR_NOT_SUPPORTED
;
1160 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1165 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1166 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1168 This is called from alloc.c:valid_pointer_p. */
1170 w32_valid_pointer_p (void *p
, int size
)
1173 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1177 unsigned char *buf
= alloca (size
);
1178 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1189 /* Converting file names from UTF-8 to either UTF-16 or the system
1192 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1194 int result
= MultiByteToWideChar (CP_UTF8
, 0, fn_in
, -1, fn_out
, MAX_PATH
);
1198 DWORD err
= GetLastError ();
1202 case ERROR_INVALID_FLAGS
:
1203 case ERROR_INVALID_PARAMETER
:
1206 case ERROR_INSUFFICIENT_BUFFER
:
1207 case ERROR_NO_UNICODE_TRANSLATION
:
1218 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1224 filename_to_ansi (const char *fn_in
, char *fn_out
)
1226 wchar_t fn_utf16
[MAXPATHLEN
];
1228 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1230 int result
= WideCharToMultiByte (CP_ACP
, 0, fn_utf16
, -1,
1231 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1235 DWORD err
= GetLastError ();
1239 case ERROR_INVALID_FLAGS
:
1240 case ERROR_INVALID_PARAMETER
:
1243 case ERROR_INSUFFICIENT_BUFFER
:
1244 case ERROR_NO_UNICODE_TRANSLATION
:
1256 filename_from_ansi (const char *fn_in
, char *fn_out
)
1263 static char startup_dir
[MAX_UTF8_PATH
];
1265 /* Get the current working directory. */
1267 getcwd (char *dir
, int dirsize
)
1274 if (dirsize
<= strlen (startup_dir
))
1280 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1284 /* Emacs doesn't actually change directory itself, it stays in the
1285 same directory where it was started. */
1286 strcpy (dir
, startup_dir
);
1291 /* Emulate getloadavg. */
1293 struct load_sample
{
1300 /* Number of processors on this machine. */
1301 static unsigned num_of_processors
;
1303 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1304 static struct load_sample samples
[16*60];
1305 static int first_idx
= -1, last_idx
= -1;
1306 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1311 int next_idx
= from
+ 1;
1313 if (next_idx
>= max_idx
)
1322 int prev_idx
= from
- 1;
1325 prev_idx
= max_idx
- 1;
1331 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1333 SYSTEM_INFO sysinfo
;
1334 FILETIME ft_idle
, ft_user
, ft_kernel
;
1336 /* Initialize the number of processors on this machine. */
1337 if (num_of_processors
<= 0)
1339 get_native_system_info (&sysinfo
);
1340 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1341 if (num_of_processors
<= 0)
1343 GetSystemInfo (&sysinfo
);
1344 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1346 if (num_of_processors
<= 0)
1347 num_of_processors
= 1;
1350 /* TODO: Take into account threads that are ready to run, by
1351 sampling the "\System\Processor Queue Length" performance
1352 counter. The code below accounts only for threads that are
1353 actually running. */
1355 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1357 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1359 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1360 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1361 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1362 *idle
= uidle
.QuadPart
;
1363 *kernel
= ukernel
.QuadPart
;
1364 *user
= uuser
.QuadPart
;
1374 /* Produce the load average for a given time interval, using the
1375 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1376 1-minute, 5-minute, or 15-minute average, respectively. */
1380 double retval
= -1.0;
1383 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1384 time_t now
= samples
[last_idx
].sample_time
;
1386 if (first_idx
!= last_idx
)
1388 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1390 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1391 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1394 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1395 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1396 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1398 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1401 if (idx
== first_idx
)
1410 getloadavg (double loadavg
[], int nelem
)
1413 ULONGLONG idle
, kernel
, user
;
1414 time_t now
= time (NULL
);
1416 /* Store another sample. We ignore samples that are less than 1 sec
1418 if (difftime (now
, samples
[last_idx
].sample_time
) >= 1.0 - 2*DBL_EPSILON
*now
)
1420 sample_system_load (&idle
, &kernel
, &user
);
1421 last_idx
= buf_next (last_idx
);
1422 samples
[last_idx
].sample_time
= now
;
1423 samples
[last_idx
].idle
= idle
;
1424 samples
[last_idx
].kernel
= kernel
;
1425 samples
[last_idx
].user
= user
;
1426 /* If the buffer has more that 15 min worth of samples, discard
1428 if (first_idx
== -1)
1429 first_idx
= last_idx
;
1430 while (first_idx
!= last_idx
1431 && (difftime (now
, samples
[first_idx
].sample_time
)
1432 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1433 first_idx
= buf_next (first_idx
);
1436 for (elem
= 0; elem
< nelem
; elem
++)
1438 double avg
= getavg (elem
);
1442 loadavg
[elem
] = avg
;
1448 /* Emulate getpwuid, getpwnam and others. */
1450 #define PASSWD_FIELD_SIZE 256
1452 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1453 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1454 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1455 static char dflt_passwd_dir
[PASSWD_FIELD_SIZE
];
1456 static char dflt_passwd_shell
[PASSWD_FIELD_SIZE
];
1458 static struct passwd dflt_passwd
=
1470 static char dflt_group_name
[GNLEN
+1];
1472 static struct group dflt_group
=
1474 /* When group information is not available, we return this as the
1475 group for all files. */
1483 return dflt_passwd
.pw_uid
;
1489 /* I could imagine arguing for checking to see whether the user is
1490 in the Administrators group and returning a UID of 0 for that
1491 case, but I don't know how wise that would be in the long run. */
1498 return dflt_passwd
.pw_gid
;
1508 getpwuid (unsigned uid
)
1510 if (uid
== dflt_passwd
.pw_uid
)
1511 return &dflt_passwd
;
1516 getgrgid (gid_t gid
)
1522 getpwnam (char *name
)
1526 pw
= getpwuid (getuid ());
1530 if (xstrcasecmp (name
, pw
->pw_name
))
1537 init_user_info (void)
1539 /* Find the user's real name by opening the process token and
1540 looking up the name associated with the user-sid in that token.
1542 Use the relative portion of the identifier authority value from
1543 the user-sid as the user id value (same for group id using the
1544 primary group sid from the process token). */
1546 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1547 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1548 DWORD glength
= sizeof (gname
);
1549 HANDLE token
= NULL
;
1550 SID_NAME_USE user_type
;
1551 unsigned char *buf
= NULL
;
1553 TOKEN_USER user_token
;
1554 TOKEN_PRIMARY_GROUP group_token
;
1557 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1560 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1561 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1563 buf
= xmalloc (blen
);
1564 result
= get_token_information (token
, TokenUser
,
1565 (LPVOID
)buf
, blen
, &needed
);
1568 memcpy (&user_token
, buf
, sizeof (user_token
));
1569 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1571 domain
, &dlength
, &user_type
);
1579 strcpy (dflt_passwd
.pw_name
, uname
);
1580 /* Determine a reasonable uid value. */
1581 if (xstrcasecmp ("administrator", uname
) == 0)
1583 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
1584 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
1588 /* Use the last sub-authority value of the RID, the relative
1589 portion of the SID, as user/group ID. */
1590 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
1592 /* Get group id and name. */
1593 result
= get_token_information (token
, TokenPrimaryGroup
,
1594 (LPVOID
)buf
, blen
, &needed
);
1595 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1597 buf
= xrealloc (buf
, blen
= needed
);
1598 result
= get_token_information (token
, TokenPrimaryGroup
,
1599 (LPVOID
)buf
, blen
, &needed
);
1603 memcpy (&group_token
, buf
, sizeof (group_token
));
1604 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
1605 dlength
= sizeof (domain
);
1606 /* If we can get at the real Primary Group name, use that.
1607 Otherwise, the default group name was already set to
1608 "None" in globals_of_w32. */
1609 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
1610 gname
, &glength
, NULL
, &dlength
,
1612 strcpy (dflt_group_name
, gname
);
1615 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1618 /* If security calls are not supported (presumably because we
1619 are running under Windows 9X), fallback to this: */
1620 else if (GetUserName (uname
, &ulength
))
1622 strcpy (dflt_passwd
.pw_name
, uname
);
1623 if (xstrcasecmp ("administrator", uname
) == 0)
1624 dflt_passwd
.pw_uid
= 0;
1626 dflt_passwd
.pw_uid
= 123;
1627 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1631 strcpy (dflt_passwd
.pw_name
, "unknown");
1632 dflt_passwd
.pw_uid
= 123;
1633 dflt_passwd
.pw_gid
= 123;
1635 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
1637 /* Ensure HOME and SHELL are defined. */
1638 if (getenv ("HOME") == NULL
)
1640 if (getenv ("SHELL") == NULL
)
1643 /* Set dir and shell from environment variables. */
1644 strcpy (dflt_passwd
.pw_dir
, getenv ("HOME"));
1645 strcpy (dflt_passwd
.pw_shell
, getenv ("SHELL"));
1649 CloseHandle (token
);
1655 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
1656 return ((rand () << 15) | rand ());
1665 /* Current codepage for encoding file names. */
1666 static int file_name_codepage
;
1668 /* Return the maximum length in bytes of a multibyte character
1669 sequence encoded in the current ANSI codepage. This is required to
1670 correctly walk the encoded file names one character at a time. */
1672 max_filename_mbslen (void)
1674 /* A simple cache to avoid calling GetCPInfo every time we need to
1675 normalize a file name. The file-name encoding is not supposed to
1676 be changed too frequently, if ever. */
1677 static Lisp_Object last_file_name_encoding
;
1678 static int last_max_mbslen
;
1679 Lisp_Object current_encoding
;
1681 current_encoding
= Vfile_name_coding_system
;
1682 if (NILP (current_encoding
))
1683 current_encoding
= Vdefault_file_name_coding_system
;
1685 if (!EQ (last_file_name_encoding
, current_encoding
))
1689 last_file_name_encoding
= current_encoding
;
1690 /* Default to the current ANSI codepage. */
1691 file_name_codepage
= w32_ansi_code_page
;
1692 if (!NILP (current_encoding
))
1694 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1695 char *cp
= NULL
, *end
;
1698 if (strncmp (cpname
, "cp", 2) == 0)
1700 else if (strncmp (cpname
, "windows-", 8) == 0)
1706 cpnum
= strtol (cp
, &end
, 10);
1707 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1708 file_name_codepage
= cpnum
;
1712 if (!file_name_codepage
)
1713 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1715 if (!GetCPInfo (file_name_codepage
, &cp_info
))
1717 file_name_codepage
= CP_ACP
;
1718 if (!GetCPInfo (file_name_codepage
, &cp_info
))
1721 last_max_mbslen
= cp_info
.MaxCharSize
;
1724 return last_max_mbslen
;
1727 /* Normalize filename by converting all path separators to
1728 the specified separator. Also conditionally convert upper
1729 case path name components to lower case. */
1732 normalize_filename (register char *fp
, char path_sep
, int multibyte
)
1736 int dbcs_p
= max_filename_mbslen () > 1;
1738 /* Multibyte file names are in the Emacs internal representation, so
1739 we can traverse them by bytes with no problems. */
1743 /* Always lower-case drive letters a-z, even if the filesystem
1744 preserves case in filenames.
1745 This is so filenames can be compared by string comparison
1746 functions that are case-sensitive. Even case-preserving filesystems
1747 do not distinguish case in drive letters. */
1749 p2
= CharNextExA (file_name_codepage
, fp
, 0);
1753 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
1759 if (multibyte
|| NILP (Vw32_downcase_file_names
))
1763 if (*fp
== '/' || *fp
== '\\')
1768 fp
= CharNextExA (file_name_codepage
, fp
, 0);
1773 sep
= path_sep
; /* convert to this path separator */
1774 elem
= fp
; /* start of current path element */
1777 if (*fp
>= 'a' && *fp
<= 'z')
1778 elem
= 0; /* don't convert this element */
1780 if (*fp
== 0 || *fp
== ':')
1782 sep
= *fp
; /* restore current separator (or 0) */
1783 *fp
= '/'; /* after conversion of this element */
1786 if (*fp
== '/' || *fp
== '\\')
1788 if (elem
&& elem
!= fp
)
1790 *fp
= 0; /* temporary end of string */
1791 _mbslwr (elem
); /* while we convert to lower case */
1793 *fp
= sep
; /* convert (or restore) path separator */
1794 elem
= fp
+ 1; /* next element starts after separator */
1802 fp
= CharNextExA (file_name_codepage
, fp
, 0);
1807 /* Destructively turn backslashes into slashes. MULTIBYTE non-zero
1808 means the file name is a multibyte string in Emacs's internal
1811 dostounix_filename (register char *p
, int multibyte
)
1813 normalize_filename (p
, '/', multibyte
);
1816 /* Destructively turn slashes into backslashes. */
1818 unixtodos_filename (register char *p
)
1820 normalize_filename (p
, '\\', 0);
1823 /* Remove all CR's that are followed by a LF.
1824 (From msdos.c...probably should figure out a way to share it,
1825 although this code isn't going to ever change.) */
1827 crlf_to_lf (register int n
, register unsigned char *buf
)
1829 unsigned char *np
= buf
;
1830 unsigned char *startp
= buf
;
1831 unsigned char *endp
= buf
+ n
;
1835 while (buf
< endp
- 1)
1839 if (*(++buf
) != 0x0a)
1850 /* Parse the root part of file name, if present. Return length and
1851 optionally store pointer to char after root. */
1853 parse_root (char * name
, char ** pPath
)
1855 char * start
= name
;
1860 /* find the root name of the volume if given */
1861 if (isalpha (name
[0]) && name
[1] == ':')
1863 /* skip past drive specifier */
1865 if (IS_DIRECTORY_SEP (name
[0]))
1868 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
1871 int dbcs_p
= max_filename_mbslen () > 1;
1876 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
1879 name
= CharNextExA (file_name_codepage
, name
, 0);
1884 if (IS_DIRECTORY_SEP (name
[0]))
1891 return name
- start
;
1894 /* Get long base name for name; name is assumed to be absolute. */
1896 get_long_basename (char * name
, char * buf
, int size
)
1898 WIN32_FIND_DATA find_data
;
1902 /* must be valid filename, no wild cards or other invalid characters */
1903 if (_mbspbrk (name
, "*?|<>\""))
1906 dir_handle
= FindFirstFile (name
, &find_data
);
1907 if (dir_handle
!= INVALID_HANDLE_VALUE
)
1909 if ((len
= strlen (find_data
.cFileName
)) < size
)
1910 memcpy (buf
, find_data
.cFileName
, len
+ 1);
1913 FindClose (dir_handle
);
1918 /* Get long name for file, if possible (assumed to be absolute). */
1920 w32_get_long_filename (char * name
, char * buf
, int size
)
1925 char full
[ MAX_PATH
];
1928 len
= strlen (name
);
1929 if (len
>= MAX_PATH
)
1932 /* Use local copy for destructive modification. */
1933 memcpy (full
, name
, len
+1);
1934 unixtodos_filename (full
);
1936 /* Copy root part verbatim. */
1937 len
= parse_root (full
, &p
);
1938 memcpy (o
, full
, len
);
1943 while (p
!= NULL
&& *p
)
1946 p
= _mbschr (q
, '\\');
1948 len
= get_long_basename (full
, o
, size
);
1971 is_unc_volume (const char *filename
)
1973 const char *ptr
= filename
;
1975 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
1978 if (_mbspbrk (ptr
+ 2, "*?|<>\"\\/"))
1984 /* Emulate the Posix unsetenv. */
1986 unsetenv (const char *name
)
1992 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
1997 name_len
= strlen (name
);
1998 /* MS docs says an environment variable cannot be longer than 32K. */
1999 if (name_len
> 32767)
2004 /* It is safe to use 'alloca' with 32K size, since the stack is at
2005 least 2MB, and we set it to 8MB in the link command line. */
2006 var
= alloca (name_len
+ 2);
2007 strncpy (var
, name
, name_len
);
2008 var
[name_len
++] = '=';
2009 var
[name_len
] = '\0';
2010 return _putenv (var
);
2013 /* MS _putenv doesn't support removing a variable when the argument
2014 does not include the '=' character, so we fix that here. */
2016 sys_putenv (char *str
)
2018 const char *const name_end
= strchr (str
, '=');
2020 if (name_end
== NULL
)
2022 /* Remove the variable from the environment. */
2023 return unsetenv (str
);
2026 return _putenv (str
);
2029 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2032 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2035 HKEY hrootkey
= NULL
;
2038 /* Check both the current user and the local machine to see if
2039 we have any resources. */
2041 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2045 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2046 && (lpvalue
= xmalloc (cbData
)) != NULL
2047 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2049 RegCloseKey (hrootkey
);
2055 RegCloseKey (hrootkey
);
2058 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2062 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2063 && (lpvalue
= xmalloc (cbData
)) != NULL
2064 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2066 RegCloseKey (hrootkey
);
2072 RegCloseKey (hrootkey
);
2078 char *get_emacs_configuration (void);
2081 init_environment (char ** argv
)
2083 static const char * const tempdirs
[] = {
2084 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2089 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2091 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2092 temporary files and assume "/tmp" if $TMPDIR is unset, which
2093 will break on DOS/Windows. Refuse to work if we cannot find
2094 a directory, not even "c:/", usable for that purpose. */
2095 for (i
= 0; i
< imax
; i
++)
2097 const char *tmp
= tempdirs
[i
];
2100 tmp
= getenv (tmp
+ 1);
2101 /* Note that `access' can lie to us if the directory resides on a
2102 read-only filesystem, like CD-ROM or a write-protected floppy.
2103 The only way to be really sure is to actually create a file and
2104 see if it succeeds. But I think that's too much to ask. */
2106 /* MSVCRT's _access crashes with D_OK. */
2107 if (tmp
&& faccessat (AT_FDCWD
, tmp
, D_OK
, AT_EACCESS
) == 0)
2109 char * var
= alloca (strlen (tmp
) + 8);
2110 sprintf (var
, "TMPDIR=%s", tmp
);
2111 _putenv (strdup (var
));
2118 Fcons (build_string ("no usable temporary directories found!!"),
2120 "While setting TMPDIR: ");
2122 /* Check for environment variables and use registry settings if they
2123 don't exist. Fallback on default values where applicable. */
2128 char locale_name
[32];
2129 char default_home
[MAX_PATH
];
2132 static const struct env_entry
2138 /* If the default value is NULL, we will use the value from the
2139 outside environment or the Registry, but will not push the
2140 variable into the Emacs environment if it is defined neither
2141 in the Registry nor in the outside environment. */
2143 {"PRELOAD_WINSOCK", NULL
},
2144 {"emacs_dir", "C:/emacs"},
2145 {"EMACSLOADPATH", NULL
},
2146 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2147 {"EMACSDATA", NULL
},
2148 {"EMACSPATH", NULL
},
2155 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2157 /* We need to copy dflt_envvars[] and work on the copy because we
2158 don't want the dumped Emacs to inherit the values of
2159 environment variables we saw during dumping (which could be on
2160 a different system). The defaults above must be left intact. */
2161 struct env_entry env_vars
[N_ENV_VARS
];
2163 for (i
= 0; i
< N_ENV_VARS
; i
++)
2164 env_vars
[i
] = dflt_envvars
[i
];
2166 /* For backwards compatibility, check if a .emacs file exists in C:/
2167 If not, then we can try to default to the appdata directory under the
2168 user's profile, which is more likely to be writable. */
2169 if (faccessat (AT_FDCWD
, "C:/.emacs", F_OK
, AT_EACCESS
) != 0)
2171 HRESULT profile_result
;
2172 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2173 of Windows 95 and NT4 that have not been updated to include
2175 ShGetFolderPath_fn get_folder_path
;
2176 get_folder_path
= (ShGetFolderPath_fn
)
2177 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2179 if (get_folder_path
!= NULL
)
2181 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2184 /* If we can't get the appdata dir, revert to old behavior. */
2185 if (profile_result
== S_OK
)
2187 env_vars
[0].def_value
= default_home
;
2193 /* Get default locale info and use it for LANG. */
2194 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2195 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2196 locale_name
, sizeof (locale_name
)))
2198 for (i
= 0; i
< N_ENV_VARS
; i
++)
2200 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2202 env_vars
[i
].def_value
= locale_name
;
2208 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2210 /* Treat emacs_dir specially: set it unconditionally based on our
2214 char modname
[MAX_PATH
];
2216 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
2218 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2222 if ((p
= _mbsrchr (modname
, '\\'))
2223 /* From bin means installed Emacs, from src means uninstalled. */
2224 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2226 char buf
[SET_ENV_BUF_SIZE
];
2227 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2230 for (p
= modname
; *p
; p
= CharNext (p
))
2231 if (*p
== '\\') *p
= '/';
2233 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2234 _putenv (strdup (buf
));
2235 /* If we are running from the Posix-like build tree, define
2236 SHELL to point to our own cmdproxy. The loop below will
2237 then disregard PATH_EXEC and the default value. */
2238 if (within_build_tree
)
2240 _snprintf (buf
, sizeof (buf
) - 1,
2241 "SHELL=%s/nt/cmdproxy.exe", modname
);
2242 _putenv (strdup (buf
));
2245 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
2247 /* FIXME: should use substring of get_emacs_configuration ().
2248 But I don't think the Windows build supports alpha, mips etc
2249 anymore, so have taken the easy option for now. */
2250 else if (p
&& (xstrcasecmp (p
, "\\i386") == 0
2251 || xstrcasecmp (p
, "\\AMD64") == 0))
2254 p
= _mbsrchr (modname
, '\\');
2258 p
= _mbsrchr (modname
, '\\');
2259 if (p
&& xstrcasecmp (p
, "\\src") == 0)
2261 char buf
[SET_ENV_BUF_SIZE
];
2264 for (p
= modname
; *p
; p
= CharNext (p
))
2265 if (*p
== '\\') *p
= '/';
2267 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2268 _putenv (strdup (buf
));
2274 for (i
= 0; i
< N_ENV_VARS
; i
++)
2276 if (!getenv (env_vars
[i
].name
))
2279 char bufc
[SET_ENV_BUF_SIZE
];
2281 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2282 /* Also ignore empty environment variables. */
2287 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2289 /* Look for cmdproxy.exe in every directory in
2290 PATH_EXEC. FIXME: This does not find cmdproxy
2291 in nt/ when we run uninstalled. */
2292 char fname
[MAX_PATH
];
2293 const char *pstart
= PATH_EXEC
, *pend
;
2296 pend
= _mbschr (pstart
, ';');
2298 pend
= pstart
+ strlen (pstart
);
2299 /* Be defensive against series of ;;; characters. */
2302 strncpy (fname
, pstart
, pend
- pstart
);
2303 fname
[pend
- pstart
] = '/';
2304 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2305 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2307 if (faccessat (AT_FDCWD
, bufc
, F_OK
, AT_EACCESS
)
2321 /* If not found in any directory, use the
2322 default as the last resort. */
2323 lpval
= env_vars
[i
].def_value
;
2324 dwType
= REG_EXPAND_SZ
;
2330 lpval
= env_vars
[i
].def_value
;
2331 dwType
= REG_EXPAND_SZ
;
2333 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2334 Vdelayed_warnings_list
2335 = Fcons (listn (CONSTYPE_HEAP
, 2,
2336 intern ("initialization"),
2337 build_string ("Setting HOME to C:\\ by default is deprecated")),
2338 Vdelayed_warnings_list
);
2343 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2345 if (dwType
== REG_EXPAND_SZ
)
2346 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2347 else if (dwType
== REG_SZ
)
2348 strcpy (buf1
, lpval
);
2349 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2351 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2353 _putenv (strdup (buf2
));
2363 /* Rebuild system configuration to reflect invoking system. */
2364 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2366 /* Another special case: on NT, the PATH variable is actually named
2367 "Path" although cmd.exe (perhaps NT itself) arranges for
2368 environment variable lookup and setting to be case insensitive.
2369 However, Emacs assumes a fully case sensitive environment, so we
2370 need to change "Path" to "PATH" to match the expectations of
2371 various elisp packages. We do this by the sneaky method of
2372 modifying the string in the C runtime environ entry.
2374 The same applies to COMSPEC. */
2378 for (envp
= environ
; *envp
; envp
++)
2379 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2380 memcpy (*envp
, "PATH=", 5);
2381 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2382 memcpy (*envp
, "COMSPEC=", 8);
2385 /* Remember the initial working directory for getcwd. */
2386 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2387 Does it matter anywhere in Emacs? */
2388 if (!GetCurrentDirectory (MAXPATHLEN
, startup_dir
))
2392 static char modname
[MAX_PATH
];
2394 if (!GetModuleFileName (NULL
, modname
, MAX_PATH
))
2399 /* Determine if there is a middle mouse button, to allow parse_button
2400 to decide whether right mouse events should be mouse-2 or
2402 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2407 /* Called from expand-file-name when default-directory is not a string. */
2410 emacs_root_dir (void)
2412 static char root_dir
[FILENAME_MAX
];
2415 p
= getenv ("emacs_dir");
2418 strcpy (root_dir
, p
);
2419 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2420 dostounix_filename (root_dir
, 0);
2424 /* We don't have scripts to automatically determine the system configuration
2425 for Emacs before it's compiled, and we don't want to have to make the
2426 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
2430 get_emacs_configuration (void)
2432 char *arch
, *oem
, *os
;
2434 static char configuration_buffer
[32];
2436 /* Determine the processor type. */
2437 switch (get_processor_type ())
2440 #ifdef PROCESSOR_INTEL_386
2441 case PROCESSOR_INTEL_386
:
2442 case PROCESSOR_INTEL_486
:
2443 case PROCESSOR_INTEL_PENTIUM
:
2451 #ifdef PROCESSOR_AMD_X8664
2452 case PROCESSOR_AMD_X8664
:
2457 #ifdef PROCESSOR_MIPS_R2000
2458 case PROCESSOR_MIPS_R2000
:
2459 case PROCESSOR_MIPS_R3000
:
2460 case PROCESSOR_MIPS_R4000
:
2465 #ifdef PROCESSOR_ALPHA_21064
2466 case PROCESSOR_ALPHA_21064
:
2476 /* Use the OEM field to reflect the compiler/library combination. */
2478 #define COMPILER_NAME "msvc"
2481 #define COMPILER_NAME "mingw"
2483 #define COMPILER_NAME "unknown"
2486 oem
= COMPILER_NAME
;
2488 switch (osinfo_cache
.dwPlatformId
) {
2489 case VER_PLATFORM_WIN32_NT
:
2491 build_num
= osinfo_cache
.dwBuildNumber
;
2493 case VER_PLATFORM_WIN32_WINDOWS
:
2494 if (osinfo_cache
.dwMinorVersion
== 0) {
2499 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
2501 case VER_PLATFORM_WIN32s
:
2502 /* Not supported, should not happen. */
2504 build_num
= LOWORD (osinfo_cache
.dwBuildNumber
);
2512 if (osinfo_cache
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) {
2513 sprintf (configuration_buffer
, "%s-%s-%s%d.%d.%d", arch
, oem
, os
,
2514 get_w32_major_version (), get_w32_minor_version (), build_num
);
2516 sprintf (configuration_buffer
, "%s-%s-%s.%d", arch
, oem
, os
, build_num
);
2519 return configuration_buffer
;
2523 get_emacs_configuration_options (void)
2525 static char *options_buffer
;
2526 char cv
[32]; /* Enough for COMPILER_VERSION. */
2528 cv
, /* To be filled later. */
2532 #ifdef ENABLE_CHECKING
2533 " --enable-checking",
2535 /* configure.bat already sets USER_CFLAGS and USER_LDFLAGS
2536 with a starting space to save work here. */
2538 " --cflags", USER_CFLAGS
,
2541 " --ldflags", USER_LDFLAGS
,
2548 /* Work out the effective configure options for this build. */
2550 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
2553 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
2555 #define COMPILER_VERSION ""
2559 if (_snprintf (cv
, sizeof (cv
) - 1, COMPILER_VERSION
) < 0)
2560 return "Error: not enough space for compiler version";
2561 cv
[sizeof (cv
) - 1] = '\0';
2563 for (i
= 0; options
[i
]; i
++)
2564 size
+= strlen (options
[i
]);
2566 options_buffer
= xmalloc (size
+ 1);
2567 options_buffer
[0] = '\0';
2569 for (i
= 0; options
[i
]; i
++)
2570 strcat (options_buffer
, options
[i
]);
2572 return options_buffer
;
2576 #include <sys/timeb.h>
2578 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2580 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2585 tv
->tv_sec
= tb
.time
;
2586 tv
->tv_usec
= tb
.millitm
* 1000L;
2587 /* Implementation note: _ftime sometimes doesn't update the dstflag
2588 according to the new timezone when the system timezone is
2589 changed. We could fix that by using GetSystemTime and
2590 GetTimeZoneInformation, but that doesn't seem necessary, since
2591 Emacs always calls gettimeofday with the 2nd argument NULL (see
2592 current_emacs_time). */
2595 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2596 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2601 /* Emulate fdutimens. */
2603 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2604 TIMESPEC[0] and TIMESPEC[1], respectively.
2605 FD must be either negative -- in which case it is ignored --
2606 or a file descriptor that is open on FILE.
2607 If FD is nonnegative, then FILE can be NULL, which means
2608 use just futimes instead of utimes.
2609 If TIMESPEC is null, FAIL.
2610 Return 0 on success, -1 (setting errno) on failure. */
2613 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2620 if (fd
< 0 && !file
)
2625 /* _futime's prototype defines 2nd arg as having the type 'struct
2626 _utimbuf', while utime needs to accept 'struct utimbuf' for
2627 compatibility with Posix. So we need to use 2 different (but
2628 equivalent) types to avoid compiler warnings, sigh. */
2631 struct _utimbuf _ut
;
2633 _ut
.actime
= timespec
[0].tv_sec
;
2634 _ut
.modtime
= timespec
[1].tv_sec
;
2635 return _futime (fd
, &_ut
);
2641 ut
.actime
= timespec
[0].tv_sec
;
2642 ut
.modtime
= timespec
[1].tv_sec
;
2643 /* Call 'utime', which is implemented below, not the MS library
2644 function, which fails on directories. */
2645 return utime (file
, &ut
);
2650 /* ------------------------------------------------------------------------- */
2651 /* IO support and wrapper functions for the Windows API. */
2652 /* ------------------------------------------------------------------------- */
2654 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2655 on network directories, so we handle that case here.
2656 (Ulrich Leodolter, 1/11/95). */
2658 sys_ctime (const time_t *t
)
2660 char *str
= (char *) ctime (t
);
2661 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2664 /* Emulate sleep...we could have done this with a define, but that
2665 would necessitate including windows.h in the files that used it.
2666 This is much easier. */
2668 sys_sleep (int seconds
)
2670 Sleep (seconds
* 1000);
2673 /* Internal MSVC functions for low-level descriptor munging */
2674 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2675 extern int __cdecl
_free_osfhnd (int fd
);
2677 /* parallel array of private info on file handles */
2678 filedesc fd_info
[ MAXDESC
];
2680 typedef struct volume_info_data
{
2681 struct volume_info_data
* next
;
2683 /* time when info was obtained */
2686 /* actual volume info */
2695 /* Global referenced by various functions. */
2696 static volume_info_data volume_info
;
2698 /* Vector to indicate which drives are local and fixed (for which cached
2699 data never expires). */
2700 static BOOL fixed_drives
[26];
2702 /* Consider cached volume information to be stale if older than 10s,
2703 at least for non-local drives. Info for fixed drives is never stale. */
2704 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2705 #define VOLINFO_STILL_VALID( root_dir, info ) \
2706 ( ( isalpha (root_dir[0]) && \
2707 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2708 || GetTickCount () - info->timestamp < 10000 )
2710 /* Cache support functions. */
2712 /* Simple linked list with linear search is sufficient. */
2713 static volume_info_data
*volume_cache
= NULL
;
2715 static volume_info_data
*
2716 lookup_volume_info (char * root_dir
)
2718 volume_info_data
* info
;
2720 for (info
= volume_cache
; info
; info
= info
->next
)
2721 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2727 add_volume_info (char * root_dir
, volume_info_data
* info
)
2729 info
->root_dir
= xstrdup (root_dir
);
2730 info
->next
= volume_cache
;
2731 volume_cache
= info
;
2735 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2736 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2737 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2738 static volume_info_data
*
2739 GetCachedVolumeInformation (char * root_dir
)
2741 volume_info_data
* info
;
2742 char default_root
[ MAX_PATH
];
2744 /* NULL for root_dir means use root from current directory. */
2745 if (root_dir
== NULL
)
2747 if (GetCurrentDirectory (MAX_PATH
, default_root
) == 0)
2749 parse_root (default_root
, &root_dir
);
2751 root_dir
= default_root
;
2754 /* Local fixed drives can be cached permanently. Removable drives
2755 cannot be cached permanently, since the volume name and serial
2756 number (if nothing else) can change. Remote drives should be
2757 treated as if they are removable, since there is no sure way to
2758 tell whether they are or not. Also, the UNC association of drive
2759 letters mapped to remote volumes can be changed at any time (even
2760 by other processes) without notice.
2762 As a compromise, so we can benefit from caching info for remote
2763 volumes, we use a simple expiry mechanism to invalidate cache
2764 entries that are more than ten seconds old. */
2767 /* No point doing this, because WNetGetConnection is even slower than
2768 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2769 GetDriveType is about the only call of this type which does not
2770 involve network access, and so is extremely quick). */
2772 /* Map drive letter to UNC if remote. */
2773 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2775 char remote_name
[ 256 ];
2776 char drive
[3] = { root_dir
[0], ':' };
2778 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2780 /* do something */ ;
2784 info
= lookup_volume_info (root_dir
);
2786 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2794 /* Info is not cached, or is stale. */
2795 if (!GetVolumeInformation (root_dir
,
2796 name
, sizeof (name
),
2800 type
, sizeof (type
)))
2803 /* Cache the volume information for future use, overwriting existing
2804 entry if present. */
2807 info
= xmalloc (sizeof (volume_info_data
));
2808 add_volume_info (root_dir
, info
);
2816 info
->name
= xstrdup (name
);
2817 info
->serialnum
= serialnum
;
2818 info
->maxcomp
= maxcomp
;
2819 info
->flags
= flags
;
2820 info
->type
= xstrdup (type
);
2821 info
->timestamp
= GetTickCount ();
2827 /* Get information on the volume where NAME is held; set path pointer to
2828 start of pathname in NAME (past UNC header\volume header if present),
2829 if pPath is non-NULL.
2831 Note: if NAME includes symlinks, the information is for the volume
2832 of the symlink, not of its target. That's because, even though
2833 GetVolumeInformation returns information about the symlink target
2834 of its argument, we only pass the root directory to
2835 GetVolumeInformation, not the full NAME. */
2837 get_volume_info (const char * name
, const char ** pPath
)
2839 char temp
[MAX_PATH
];
2840 char *rootname
= NULL
; /* default to current volume */
2841 volume_info_data
* info
;
2846 /* Find the root name of the volume if given. */
2847 if (isalpha (name
[0]) && name
[1] == ':')
2855 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2859 int dbcs_p
= max_filename_mbslen () > 1;
2864 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2870 const char *p
= name
;
2872 name
= CharNextExA (file_name_codepage
, name
, 0);
2873 memcpy (str
, p
, name
- p
);
2886 info
= GetCachedVolumeInformation (rootname
);
2889 /* Set global referenced by other functions. */
2890 volume_info
= *info
;
2896 /* Determine if volume is FAT format (ie. only supports short 8.3
2897 names); also set path pointer to start of pathname in name, if
2898 pPath is non-NULL. */
2900 is_fat_volume (const char * name
, const char ** pPath
)
2902 if (get_volume_info (name
, pPath
))
2903 return (volume_info
.maxcomp
== 12);
2907 /* Map filename to a valid 8.3 name if necessary.
2908 The result is a pointer to a static buffer, so CAVEAT EMPTOR! */
2910 map_w32_filename (const char * name
, const char ** pPath
)
2912 static char shortname
[MAX_PATH
];
2913 char * str
= shortname
;
2916 const char * save_name
= name
;
2918 if (strlen (name
) >= MAX_PATH
)
2920 /* Return a filename which will cause callers to fail. */
2921 strcpy (shortname
, "?");
2925 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
2927 register int left
= 8; /* maximum number of chars in part */
2928 register int extn
= 0; /* extension added? */
2929 register int dots
= 2; /* maximum number of dots allowed */
2932 *str
++ = *name
++; /* skip past UNC header */
2934 while ((c
= *name
++))
2941 *str
++ = (c
== ':' ? ':' : '\\');
2942 extn
= 0; /* reset extension flags */
2943 dots
= 2; /* max 2 dots */
2944 left
= 8; /* max length 8 for main part */
2949 /* Convert path components of the form .xxx to _xxx,
2950 but leave . and .. as they are. This allows .emacs
2951 to be read as _emacs, for example. */
2955 IS_DIRECTORY_SEP (*name
))
2970 extn
= 1; /* we've got an extension */
2971 left
= 3; /* 3 chars in extension */
2975 /* any embedded dots after the first are converted to _ */
2980 case '#': /* don't lose these, they're important */
2982 str
[-1] = c
; /* replace last character of part */
2987 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
2989 dots
= 0; /* started a path component */
2998 strcpy (shortname
, name
);
2999 unixtodos_filename (shortname
);
3003 *pPath
= shortname
+ (path
- save_name
);
3009 is_exec (const char * name
)
3011 char * p
= strrchr (name
, '.');
3014 && (xstrcasecmp (p
, ".exe") == 0 ||
3015 xstrcasecmp (p
, ".com") == 0 ||
3016 xstrcasecmp (p
, ".bat") == 0 ||
3017 xstrcasecmp (p
, ".cmd") == 0));
3020 /* Emulate the Unix directory procedures opendir, closedir,
3021 and readdir. We can't use the procedures supplied in sysdep.c,
3022 so we provide them here. */
3024 struct dirent dir_static
; /* simulated directory contents */
3025 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3026 static int dir_is_fat
;
3027 static char dir_pathname
[MAXPATHLEN
+1];
3028 static WIN32_FIND_DATA dir_find_data
;
3030 /* Support shares on a network resource as subdirectories of a read-only
3032 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3033 static HANDLE
open_unc_volume (const char *);
3034 static char *read_unc_volume (HANDLE
, char *, int);
3035 static void close_unc_volume (HANDLE
);
3038 opendir (const char *filename
)
3042 /* Opening is done by FindFirstFile. However, a read is inherent to
3043 this operation, so we defer the open until read time. */
3045 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3047 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3050 /* Note: We don't support traversal of UNC volumes via symlinks.
3051 Doing so would mean punishing 99.99% of use cases by resolving
3052 all the possible symlinks in FILENAME, recursively. */
3053 if (is_unc_volume (filename
))
3055 wnet_enum_handle
= open_unc_volume (filename
);
3056 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3060 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3067 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAXPATHLEN
);
3068 dir_pathname
[MAXPATHLEN
] = '\0';
3069 /* Note: We don't support symlinks to file names on FAT volumes.
3070 Doing so would mean punishing 99.99% of use cases by resolving
3071 all the possible symlinks in FILENAME, recursively. */
3072 dir_is_fat
= is_fat_volume (filename
, NULL
);
3078 closedir (DIR *dirp
)
3080 /* If we have a find-handle open, close it. */
3081 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3083 FindClose (dir_find_handle
);
3084 dir_find_handle
= INVALID_HANDLE_VALUE
;
3086 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3088 close_unc_volume (wnet_enum_handle
);
3089 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3091 xfree ((char *) dirp
);
3097 int downcase
= !NILP (Vw32_downcase_file_names
);
3099 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3101 if (!read_unc_volume (wnet_enum_handle
,
3102 dir_find_data
.cFileName
,
3106 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3107 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3109 char filename
[MAXNAMLEN
+ 3];
3111 int dbcs_p
= max_filename_mbslen () > 1;
3113 strcpy (filename
, dir_pathname
);
3114 ln
= strlen (filename
) - 1;
3117 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3118 strcat (filename
, "\\");
3122 char *end
= filename
+ ln
+ 1;
3123 char *last_char
= CharPrevExA (file_name_codepage
, filename
, end
, 0);
3125 if (!IS_DIRECTORY_SEP (*last_char
))
3126 strcat (filename
, "\\");
3128 strcat (filename
, "*");
3130 /* Note: No need to resolve symlinks in FILENAME, because
3131 FindFirst opens the directory that is the target of a
3133 dir_find_handle
= FindFirstFile (filename
, &dir_find_data
);
3135 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3140 if (!FindNextFile (dir_find_handle
, &dir_find_data
))
3144 /* Emacs never uses this value, so don't bother making it match
3145 value returned by stat(). */
3146 dir_static
.d_ino
= 1;
3148 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
3150 /* If the file name in cFileName[] includes `?' characters, it means
3151 the original file name used characters that cannot be represented
3152 by the current ANSI codepage. To avoid total lossage, retrieve
3153 the short 8+3 alias of the long file name. */
3154 if (_mbspbrk (dir_static
.d_name
, "?"))
3156 strcpy (dir_static
.d_name
, dir_find_data
.cAlternateFileName
);
3157 downcase
= 1; /* 8+3 aliases are returned in all caps */
3159 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3160 dir_static
.d_reclen
= sizeof (struct dirent
) - MAXNAMLEN
+ 3 +
3161 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3163 /* If the file name in cFileName[] includes `?' characters, it means
3164 the original file name used characters that cannot be represented
3165 by the current ANSI codepage. To avoid total lossage, retrieve
3166 the short 8+3 alias of the long file name. */
3167 if (_mbspbrk (dir_find_data
.cFileName
, "?"))
3169 strcpy (dir_static
.d_name
, dir_find_data
.cAlternateFileName
);
3170 /* 8+3 aliases are returned in all caps, which could break
3171 various alists that look at filenames' extensions. */
3175 strcpy (dir_static
.d_name
, dir_find_data
.cFileName
);
3176 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3178 _mbslwr (dir_static
.d_name
);
3182 int dbcs_p
= max_filename_mbslen () > 1;
3183 for (p
= dir_static
.d_name
; *p
; )
3185 if (*p
>= 'a' && *p
<= 'z')
3188 p
= CharNextExA (file_name_codepage
, p
, 0);
3193 _mbslwr (dir_static
.d_name
);
3200 open_unc_volume (const char *path
)
3206 nr
.dwScope
= RESOURCE_GLOBALNET
;
3207 nr
.dwType
= RESOURCETYPE_DISK
;
3208 nr
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3209 nr
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3210 nr
.lpLocalName
= NULL
;
3211 nr
.lpRemoteName
= (LPSTR
)map_w32_filename (path
, NULL
);
3212 nr
.lpComment
= NULL
;
3213 nr
.lpProvider
= NULL
;
3215 result
= WNetOpenEnum (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3216 RESOURCEUSAGE_CONNECTABLE
, &nr
, &henum
);
3218 if (result
== NO_ERROR
)
3221 return INVALID_HANDLE_VALUE
;
3225 read_unc_volume (HANDLE henum
, char *readbuf
, int size
)
3229 DWORD bufsize
= 512;
3232 int dbcs_p
= max_filename_mbslen () > 1;
3235 buffer
= alloca (bufsize
);
3236 result
= WNetEnumResource (henum
, &count
, buffer
, &bufsize
);
3237 if (result
!= NO_ERROR
)
3240 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3241 ptr
= ((LPNETRESOURCE
) buffer
)->lpRemoteName
;
3244 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
)) ptr
++;
3247 while (*ptr
&& !IS_DIRECTORY_SEP (*ptr
))
3248 ptr
= CharNextExA (file_name_codepage
, ptr
, 0);
3252 strncpy (readbuf
, ptr
, size
);
3257 close_unc_volume (HANDLE henum
)
3259 if (henum
!= INVALID_HANDLE_VALUE
)
3260 WNetCloseEnum (henum
);
3264 unc_volume_file_attributes (const char *path
)
3269 henum
= open_unc_volume (path
);
3270 if (henum
== INVALID_HANDLE_VALUE
)
3273 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3275 close_unc_volume (henum
);
3280 /* Ensure a network connection is authenticated. */
3282 logon_network_drive (const char *path
)
3284 NETRESOURCE resource
;
3285 char share
[MAX_PATH
];
3292 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3293 drvtype
= DRIVE_REMOTE
;
3294 else if (path
[0] == '\0' || path
[1] != ':')
3295 drvtype
= GetDriveType (NULL
);
3302 drvtype
= GetDriveType (drive
);
3305 /* Only logon to networked drives. */
3306 if (drvtype
!= DRIVE_REMOTE
)
3310 strncpy (share
, path
, MAX_PATH
);
3311 /* Truncate to just server and share name. */
3312 dbcs_p
= max_filename_mbslen () > 1;
3313 for (p
= share
+ 2; *p
&& p
< share
+ MAX_PATH
; )
3315 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3321 p
= CharNextExA (file_name_codepage
, p
, 0);
3326 resource
.dwType
= RESOURCETYPE_DISK
;
3327 resource
.lpLocalName
= NULL
;
3328 resource
.lpRemoteName
= share
;
3329 resource
.lpProvider
= NULL
;
3331 WNetAddConnection2 (&resource
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3334 /* Emulate faccessat(2). */
3336 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3340 if (dirfd
!= AT_FDCWD
3341 && !(IS_DIRECTORY_SEP (path
[0])
3342 || IS_DEVICE_SEP (path
[1])))
3348 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3349 newer versions blow up when passed D_OK. */
3350 path
= map_w32_filename (path
, NULL
);
3351 /* If the last element of PATH is a symlink, we need to resolve it
3352 to get the attributes of its target file. Note: any symlinks in
3353 PATH elements other than the last one are transparently resolved
3354 by GetFileAttributes below. */
3355 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3356 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3357 path
= chase_symlinks (path
);
3359 if ((attributes
= GetFileAttributes (path
)) == -1)
3361 DWORD w32err
= GetLastError ();
3365 case ERROR_INVALID_NAME
:
3366 case ERROR_BAD_PATHNAME
:
3367 if (is_unc_volume (path
))
3369 attributes
= unc_volume_file_attributes (path
);
3370 if (attributes
== -1)
3378 case ERROR_FILE_NOT_FOUND
:
3379 case ERROR_BAD_NETPATH
:
3388 if ((mode
& X_OK
) != 0
3389 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3394 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3399 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3407 /* Shadow some MSVC runtime functions to map requests for long filenames
3408 to reasonable short names if necessary. This was originally added to
3409 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3413 sys_chdir (const char * path
)
3415 /* FIXME: Temporary. Also, figure out what to do with
3416 map_w32_filename, as the original code did this:
3417 _chdir(map_w32_filename (path, NULL)). */
3418 if (w32_unicode_filenames
)
3420 wchar_t newdir
[MAXPATHLEN
];
3422 if (filename_to_utf16 (path
, newdir
) == 0)
3423 return _wchdir (newdir
);
3428 char newdir
[MAXPATHLEN
];
3430 if (filename_to_ansi (path
, newdir
) == 0)
3431 return _chdir (path
);
3437 sys_chmod (const char * path
, int mode
)
3439 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3440 return _chmod (path
, mode
);
3444 sys_creat (const char * path
, int mode
)
3446 return _creat (map_w32_filename (path
, NULL
), mode
);
3450 sys_fopen (const char * path
, const char * mode
)
3454 const char * mode_save
= mode
;
3456 /* Force all file handles to be non-inheritable. This is necessary to
3457 ensure child processes don't unwittingly inherit handles that might
3458 prevent future file access. */
3462 else if (mode
[0] == 'w' || mode
[0] == 'a')
3463 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3467 /* Only do simplistic option parsing. */
3471 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3474 else if (mode
[0] == 'b')
3479 else if (mode
[0] == 't')
3486 fd
= _open (map_w32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
3490 return _fdopen (fd
, mode_save
);
3493 /* This only works on NTFS volumes, but is useful to have. */
3495 sys_link (const char * old
, const char * new)
3499 char oldname
[MAX_PATH
], newname
[MAX_PATH
];
3501 if (old
== NULL
|| new == NULL
)
3507 strcpy (oldname
, map_w32_filename (old
, NULL
));
3508 strcpy (newname
, map_w32_filename (new, NULL
));
3510 fileh
= CreateFile (oldname
, 0, 0, NULL
, OPEN_EXISTING
,
3511 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3512 if (fileh
!= INVALID_HANDLE_VALUE
)
3516 /* Confusingly, the "alternate" stream name field does not apply
3517 when restoring a hard link, and instead contains the actual
3518 stream data for the link (ie. the name of the link to create).
3519 The WIN32_STREAM_ID structure before the cStreamName field is
3520 the stream header, which is then immediately followed by the
3524 WIN32_STREAM_ID wid
;
3525 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3528 wlen
= MultiByteToWideChar (CP_ACP
, MB_PRECOMPOSED
, newname
, -1,
3529 data
.wid
.cStreamName
, MAX_PATH
);
3532 LPVOID context
= NULL
;
3535 data
.wid
.dwStreamId
= BACKUP_LINK
;
3536 data
.wid
.dwStreamAttributes
= 0;
3537 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3538 data
.wid
.Size
.HighPart
= 0;
3539 data
.wid
.dwStreamNameSize
= 0;
3541 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3542 offsetof (WIN32_STREAM_ID
, cStreamName
)
3543 + data
.wid
.Size
.LowPart
,
3544 &wbytes
, FALSE
, FALSE
, &context
)
3545 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3552 /* Should try mapping GetLastError to errno; for now just
3553 indicate a general error (eg. links not supported). */
3554 errno
= EINVAL
; // perhaps EMLINK?
3558 CloseHandle (fileh
);
3567 sys_mkdir (const char * path
)
3569 return _mkdir (map_w32_filename (path
, NULL
));
3573 sys_open (const char * path
, int oflag
, int mode
)
3575 const char* mpath
= map_w32_filename (path
, NULL
);
3578 /* If possible, try to open file without _O_CREAT, to be able to
3579 write to existing hidden and system files. Force all file
3580 handles to be non-inheritable. */
3581 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
3582 res
= _open (mpath
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
3584 res
= _open (mpath
, oflag
| _O_NOINHERIT
, mode
);
3589 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
3592 Standard algorithm for generating a temporary file name seems to be
3593 use pid or tid with a letter on the front (in place of the 6 X's)
3594 and cycle through the letters to find a unique name. We extend
3595 that to allow any reasonable character as the first of the 6 X's,
3596 so that the number of simultaneously used temporary files will be
3600 mkostemp (char * template, int flags
)
3604 unsigned uid
= GetCurrentThreadId ();
3605 int save_errno
= errno
;
3606 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
3609 if (template == NULL
)
3612 p
= template + strlen (template);
3614 /* replace up to the last 5 X's with uid in decimal */
3615 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
3617 p
[0] = '0' + uid
% 10;
3621 if (i
< 0 && p
[0] == 'X')
3626 p
[0] = first_char
[i
];
3627 if ((fd
= sys_open (template,
3628 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
3629 S_IRUSR
| S_IWUSR
)) >= 0
3637 while (++i
< sizeof (first_char
));
3640 /* Template is badly formed or else we can't generate a unique name. */
3645 fchmod (int fd
, mode_t mode
)
3651 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
3654 char temp
[MAX_PATH
];
3658 /* MoveFile on Windows 95 doesn't correctly change the short file name
3659 alias in a number of circumstances (it is not easy to predict when
3660 just by looking at oldname and newname, unfortunately). In these
3661 cases, renaming through a temporary name avoids the problem.
3663 A second problem on Windows 95 is that renaming through a temp name when
3664 newname is uppercase fails (the final long name ends up in
3665 lowercase, although the short alias might be uppercase) UNLESS the
3666 long temp name is not 8.3.
3668 So, on Windows 95 we always rename through a temp name, and we make sure
3669 the temp name has a long extension to ensure correct renaming. */
3671 strcpy (temp
, map_w32_filename (oldname
, NULL
));
3673 /* volume_info is set indirectly by map_w32_filename. */
3674 oldname_dev
= volume_info
.serialnum
;
3676 if (os_subtype
== OS_9X
)
3682 oldname
= map_w32_filename (oldname
, NULL
);
3683 if ((o
= strrchr (oldname
, '\\')))
3686 o
= (char *) oldname
;
3688 if ((p
= strrchr (temp
, '\\')))
3695 /* Force temp name to require a manufactured 8.3 alias - this
3696 seems to make the second rename work properly. */
3697 sprintf (p
, "_.%s.%u", o
, i
);
3699 result
= rename (oldname
, temp
);
3701 /* This loop must surely terminate! */
3702 while (result
< 0 && errno
== EEXIST
);
3707 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
3708 (at least if it is a file; don't do this for directories).
3710 Since we mustn't do this if we are just changing the case of the
3711 file name (we would end up deleting the file we are trying to
3712 rename!), we let rename detect if the destination file already
3713 exists - that way we avoid the possible pitfalls of trying to
3714 determine ourselves whether two names really refer to the same
3715 file, which is not always possible in the general case. (Consider
3716 all the permutations of shared or subst'd drives, etc.) */
3718 newname
= map_w32_filename (newname
, NULL
);
3720 /* volume_info is set indirectly by map_w32_filename. */
3721 newname_dev
= volume_info
.serialnum
;
3723 result
= rename (temp
, newname
);
3725 if (result
< 0 && force
)
3727 DWORD w32err
= GetLastError ();
3730 && newname_dev
!= oldname_dev
)
3732 /* The implementation of `rename' on Windows does not return
3733 errno = EXDEV when you are moving a directory to a
3734 different storage device (ex. logical disk). It returns
3735 EACCES instead. So here we handle such situations and
3739 if ((attributes
= GetFileAttributes (temp
)) != -1
3740 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3743 else if (errno
== EEXIST
)
3745 if (_chmod (newname
, 0666) != 0)
3747 if (_unlink (newname
) != 0)
3749 result
= rename (temp
, newname
);
3751 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
3752 && is_symlink (temp
))
3754 /* This is Windows prohibiting the user from creating a
3755 symlink in another place, since that requires
3765 sys_rename (char const *old
, char const *new)
3767 return sys_rename_replace (old
, new, TRUE
);
3771 sys_rmdir (const char * path
)
3773 return _rmdir (map_w32_filename (path
, NULL
));
3777 sys_unlink (const char * path
)
3779 path
= map_w32_filename (path
, NULL
);
3781 /* On Unix, unlink works without write permission. */
3782 _chmod (path
, 0666);
3783 return _unlink (path
);
3786 static FILETIME utc_base_ft
;
3787 static ULONGLONG utc_base
; /* In 100ns units */
3788 static int init
= 0;
3790 #define FILETIME_TO_U64(result, ft) \
3792 ULARGE_INTEGER uiTemp; \
3793 uiTemp.LowPart = (ft).dwLowDateTime; \
3794 uiTemp.HighPart = (ft).dwHighDateTime; \
3795 result = uiTemp.QuadPart; \
3799 initialize_utc_base (void)
3801 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
3810 st
.wMilliseconds
= 0;
3812 SystemTimeToFileTime (&st
, &utc_base_ft
);
3813 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
3817 convert_time (FILETIME ft
)
3823 initialize_utc_base ();
3827 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
3830 FILETIME_TO_U64 (tmp
, ft
);
3831 return (time_t) ((tmp
- utc_base
) / 10000000L);
3835 convert_from_time_t (time_t time
, FILETIME
* pft
)
3841 initialize_utc_base ();
3845 /* time in 100ns units since 1-Jan-1601 */
3846 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
3847 pft
->dwHighDateTime
= tmp
.HighPart
;
3848 pft
->dwLowDateTime
= tmp
.LowPart
;
3852 /* No reason to keep this; faking inode values either by hashing or even
3853 using the file index from GetInformationByHandle, is not perfect and
3854 so by default Emacs doesn't use the inode values on Windows.
3855 Instead, we now determine file-truename correctly (except for
3856 possible drive aliasing etc). */
3858 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
3860 hashval (const unsigned char * str
)
3865 h
= (h
<< 4) + *str
++;
3871 /* Return the hash value of the canonical pathname, excluding the
3872 drive/UNC header, to get a hopefully unique inode number. */
3874 generate_inode_val (const char * name
)
3876 char fullname
[ MAX_PATH
];
3880 /* Get the truly canonical filename, if it exists. (Note: this
3881 doesn't resolve aliasing due to subst commands, or recognize hard
3883 if (!w32_get_long_filename ((char *)name
, fullname
, MAX_PATH
))
3886 parse_root (fullname
, &p
);
3887 /* Normal W32 filesystems are still case insensitive. */
3894 static PSECURITY_DESCRIPTOR
3895 get_file_security_desc_by_handle (HANDLE h
)
3897 PSECURITY_DESCRIPTOR psd
= NULL
;
3899 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
3900 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
3902 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
3903 NULL
, NULL
, NULL
, NULL
, &psd
);
3904 if (err
!= ERROR_SUCCESS
)
3910 static PSECURITY_DESCRIPTOR
3911 get_file_security_desc_by_name (const char *fname
)
3913 PSECURITY_DESCRIPTOR psd
= NULL
;
3915 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
3916 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
3918 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
3920 err
= GetLastError ();
3921 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
3925 psd
= xmalloc (sd_len
);
3926 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
3938 unsigned n_subauthorities
;
3940 /* Use the last sub-authority value of the RID, the relative
3941 portion of the SID, as user/group ID. */
3942 n_subauthorities
= *get_sid_sub_authority_count (sid
);
3943 if (n_subauthorities
< 1)
3944 return 0; /* the "World" RID */
3945 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
3948 /* Caching SID and account values for faster lokup. */
3952 struct w32_id
*next
;
3954 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
3957 static struct w32_id
*w32_idlist
;
3960 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
3962 struct w32_id
*tail
, *found
;
3964 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
3966 if (equal_sid ((PSID
)tail
->sid
, sid
))
3975 strcpy (name
, found
->name
);
3983 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
3986 struct w32_id
*new_entry
;
3988 /* We don't want to leave behind stale cache from when Emacs was
3992 sid_len
= get_length_sid (sid
);
3993 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
3996 new_entry
->rid
= id
;
3997 strcpy (new_entry
->name
, name
);
3998 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
3999 new_entry
->next
= w32_idlist
;
4000 w32_idlist
= new_entry
;
4009 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4013 SID_NAME_USE ignore
;
4015 DWORD name_len
= sizeof (name
);
4017 DWORD domain_len
= sizeof (domain
);
4022 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4023 else if (what
== GID
)
4024 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4028 if (!result
|| !is_valid_sid (sid
))
4030 else if (!w32_cached_id (sid
, id
, nm
))
4032 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4033 domain
, &domain_len
, &ignore
)
4034 || name_len
> UNLEN
+1)
4038 *id
= get_rid (sid
);
4040 w32_add_to_cache (sid
, *id
, name
);
4047 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4049 int dflt_usr
= 0, dflt_grp
= 0;
4058 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4060 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4063 /* Consider files to belong to current user/group, if we cannot get
4064 more accurate information. */
4067 st
->st_uid
= dflt_passwd
.pw_uid
;
4068 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4072 st
->st_gid
= dflt_passwd
.pw_gid
;
4073 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4077 /* Return non-zero if NAME is a potentially slow filesystem. */
4079 is_slow_fs (const char *name
)
4084 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4085 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4086 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4087 devtype
= GetDriveType (NULL
); /* use root of current drive */
4090 /* GetDriveType needs the root directory of the drive. */
4091 strncpy (drive_root
, name
, 2);
4092 drive_root
[2] = '\\';
4093 drive_root
[3] = '\0';
4094 devtype
= GetDriveType (drive_root
);
4096 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4099 /* If this is non-zero, the caller wants accurate information about
4100 file's owner and group, which could be expensive to get. */
4101 int w32_stat_get_owner_group
;
4103 /* MSVC stat function can't cope with UNC names and has other bugs, so
4104 replace it with our own. This also allows us to calculate consistent
4105 inode values and owner/group without hacks in the main Emacs code. */
4108 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4110 char *name
, *save_name
, *r
;
4111 WIN32_FIND_DATA wfd
;
4113 unsigned __int64 fake_inode
= 0;
4116 int rootdir
= FALSE
;
4117 PSECURITY_DESCRIPTOR psd
= NULL
;
4118 int is_a_symlink
= 0;
4119 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4120 DWORD access_rights
= 0;
4121 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4122 FILETIME ctime
, atime
, wtime
;
4125 if (path
== NULL
|| buf
== NULL
)
4131 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4132 /* Must be valid filename, no wild cards or other invalid
4133 characters. We use _mbspbrk to support multibyte strings that
4134 might look to strpbrk as if they included literal *, ?, and other
4135 characters mentioned below that are disallowed by Windows
4137 if (_mbspbrk (name
, "*?|<>\""))
4143 /* Remove trailing directory separator, unless name is the root
4144 directory of a drive or UNC volume in which case ensure there
4145 is a trailing separator. */
4146 len
= strlen (name
);
4147 name
= strcpy (alloca (len
+ 2), name
);
4149 /* Avoid a somewhat costly call to is_symlink if the filesystem
4150 doesn't support symlinks. */
4151 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4152 is_a_symlink
= is_symlink (name
);
4154 /* Plan A: Open the file and get all the necessary information via
4155 the resulting handle. This solves several issues in one blow:
4157 . retrieves attributes for the target of a symlink, if needed
4158 . gets attributes of root directories and symlinks pointing to
4159 root directories, thus avoiding the need for special-casing
4160 these and detecting them by examining the file-name format
4161 . retrieves more accurate attributes (e.g., non-zero size for
4162 some directories, esp. directories that are junction points)
4163 . correctly resolves "c:/..", "/.." and similar file names
4164 . avoids run-time penalties for 99% of use cases
4166 Plan A is always tried first, unless the user asked not to (but
4167 if the file is a symlink and we need to follow links, we try Plan
4168 A even if the user asked not to).
4170 If Plan A fails, we go to Plan B (below), where various
4171 potentially expensive techniques must be used to handle "special"
4172 files such as UNC volumes etc. */
4173 if (!(NILP (Vw32_get_true_file_attributes
)
4174 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4175 /* Following symlinks requires getting the info by handle. */
4176 || (is_a_symlink
&& follow_symlinks
))
4178 BY_HANDLE_FILE_INFORMATION info
;
4180 if (is_a_symlink
&& !follow_symlinks
)
4181 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4182 /* READ_CONTROL access rights are required to get security info
4183 by handle. But if the OS doesn't support security in the
4184 first place, we don't need to try. */
4185 if (is_windows_9x () != TRUE
)
4186 access_rights
|= READ_CONTROL
;
4188 fh
= CreateFile (name
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4190 /* If CreateFile fails with READ_CONTROL, try again with zero as
4192 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4193 fh
= CreateFile (name
, 0, 0, NULL
, OPEN_EXISTING
,
4195 if (fh
== INVALID_HANDLE_VALUE
)
4196 goto no_true_file_attributes
;
4198 /* This is more accurate in terms of getting the correct number
4199 of links, but is quite slow (it is noticeable when Emacs is
4200 making a list of file name completions). */
4201 if (GetFileInformationByHandle (fh
, &info
))
4203 nlinks
= info
.nNumberOfLinks
;
4204 /* Might as well use file index to fake inode values, but this
4205 is not guaranteed to be unique unless we keep a handle open
4206 all the time (even then there are situations where it is
4207 not unique). Reputedly, there are at most 48 bits of info
4208 (on NTFS, presumably less on FAT). */
4209 fake_inode
= info
.nFileIndexHigh
;
4211 fake_inode
+= info
.nFileIndexLow
;
4212 serialnum
= info
.dwVolumeSerialNumber
;
4213 fs_high
= info
.nFileSizeHigh
;
4214 fs_low
= info
.nFileSizeLow
;
4215 ctime
= info
.ftCreationTime
;
4216 atime
= info
.ftLastAccessTime
;
4217 wtime
= info
.ftLastWriteTime
;
4218 fattrs
= info
.dwFileAttributes
;
4222 /* We don't go to Plan B here, because it's not clear that
4223 it's a good idea. The only known use case where
4224 CreateFile succeeds, but GetFileInformationByHandle fails
4225 (with ERROR_INVALID_FUNCTION) is for character devices
4226 such as NUL, PRN, etc. For these, switching to Plan B is
4227 a net loss, because we lose the character device
4228 attribute returned by GetFileType below (FindFirstFile
4229 doesn't set that bit in the attributes), and the other
4230 fields don't make sense for character devices anyway.
4231 Emacs doesn't really care for non-file entities in the
4232 context of l?stat, so neither do we. */
4234 /* w32err is assigned so one could put a breakpoint here and
4235 examine its value, when GetFileInformationByHandle
4237 DWORD w32err
= GetLastError ();
4241 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4247 /* Test for a symlink before testing for a directory, since
4248 symlinks to directories have the directory bit set, but we
4249 don't want them to appear as directories. */
4250 if (is_a_symlink
&& !follow_symlinks
)
4251 buf
->st_mode
= S_IFLNK
;
4252 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4253 buf
->st_mode
= S_IFDIR
;
4256 DWORD ftype
= GetFileType (fh
);
4260 case FILE_TYPE_DISK
:
4261 buf
->st_mode
= S_IFREG
;
4263 case FILE_TYPE_PIPE
:
4264 buf
->st_mode
= S_IFIFO
;
4266 case FILE_TYPE_CHAR
:
4267 case FILE_TYPE_UNKNOWN
:
4269 buf
->st_mode
= S_IFCHR
;
4272 /* We produce the fallback owner and group data, based on the
4273 current user that runs Emacs, in the following cases:
4275 . caller didn't request owner and group info
4276 . this is Windows 9X
4277 . getting security by handle failed, and we need to produce
4278 information for the target of a symlink (this is better
4279 than producing a potentially misleading info about the
4282 If getting security by handle fails, and we don't need to
4283 resolve symlinks, we try getting security by name. */
4284 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4285 get_file_owner_and_group (NULL
, buf
);
4288 psd
= get_file_security_desc_by_handle (fh
);
4291 get_file_owner_and_group (psd
, buf
);
4294 else if (!(is_a_symlink
&& follow_symlinks
))
4296 psd
= get_file_security_desc_by_name (name
);
4297 get_file_owner_and_group (psd
, buf
);
4301 get_file_owner_and_group (NULL
, buf
);
4307 no_true_file_attributes
:
4308 /* Plan B: Either getting a handle on the file failed, or the
4309 caller explicitly asked us to not bother making this
4310 information more accurate.
4312 Implementation note: In Plan B, we never bother to resolve
4313 symlinks, even if we got here because we tried Plan A and
4314 failed. That's because, even if the caller asked for extra
4315 precision by setting Vw32_get_true_file_attributes to t,
4316 resolving symlinks requires acquiring a file handle to the
4317 symlink, which we already know will fail. And if the user
4318 did not ask for extra precision, resolving symlinks will fly
4319 in the face of that request, since the user then wants the
4320 lightweight version of the code. */
4321 dbcs_p
= max_filename_mbslen () > 1;
4322 rootdir
= (path
>= save_name
+ len
- 1
4323 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4325 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4326 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4327 if (IS_DIRECTORY_SEP (r
[0])
4328 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4331 /* Note: If NAME is a symlink to the root of a UNC volume
4332 (i.e. "\\SERVER"), we will not detect that here, and we will
4333 return data about the symlink as result of FindFirst below.
4334 This is unfortunate, but that marginal use case does not
4335 justify a call to chase_symlinks which would impose a penalty
4336 on all the other use cases. (We get here for symlinks to
4337 roots of UNC volumes because CreateFile above fails for them,
4338 unlike with symlinks to root directories X:\ of drives.) */
4339 if (is_unc_volume (name
))
4341 fattrs
= unc_volume_file_attributes (name
);
4345 ctime
= atime
= wtime
= utc_base_ft
;
4351 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4352 strcat (name
, "\\");
4356 char *end
= name
+ len
;
4357 char *n
= CharPrevExA (file_name_codepage
, name
, end
, 0);
4359 if (!IS_DIRECTORY_SEP (*n
))
4360 strcat (name
, "\\");
4362 if (GetDriveType (name
) < 2)
4368 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4369 ctime
= atime
= wtime
= utc_base_ft
;
4375 if (IS_DIRECTORY_SEP (name
[len
-1]))
4380 char *end
= name
+ len
;
4381 char *n
= CharPrevExA (file_name_codepage
, name
, end
, 0);
4383 if (IS_DIRECTORY_SEP (*n
))
4387 /* (This is hacky, but helps when doing file completions on
4388 network drives.) Optimize by using information available from
4389 active readdir if possible. */
4390 len
= strlen (dir_pathname
);
4393 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4398 char *end
= dir_pathname
+ len
;
4399 char *n
= CharPrevExA (file_name_codepage
, dir_pathname
, end
, 0);
4401 if (IS_DIRECTORY_SEP (*n
))
4404 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4405 && !(is_a_symlink
&& follow_symlinks
)
4406 && strnicmp (save_name
, dir_pathname
, len
) == 0
4407 && IS_DIRECTORY_SEP (name
[len
])
4408 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4410 /* This was the last entry returned by readdir. */
4411 wfd
= dir_find_data
;
4415 logon_network_drive (name
);
4417 fh
= FindFirstFile (name
, &wfd
);
4418 if (fh
== INVALID_HANDLE_VALUE
)
4425 /* Note: if NAME is a symlink, the information we get from
4426 FindFirstFile is for the symlink, not its target. */
4427 fattrs
= wfd
.dwFileAttributes
;
4428 ctime
= wfd
.ftCreationTime
;
4429 atime
= wfd
.ftLastAccessTime
;
4430 wtime
= wfd
.ftLastWriteTime
;
4431 fs_high
= wfd
.nFileSizeHigh
;
4432 fs_low
= wfd
.nFileSizeLow
;
4435 serialnum
= volume_info
.serialnum
;
4437 if (is_a_symlink
&& !follow_symlinks
)
4438 buf
->st_mode
= S_IFLNK
;
4439 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4440 buf
->st_mode
= S_IFDIR
;
4442 buf
->st_mode
= S_IFREG
;
4444 get_file_owner_and_group (NULL
, buf
);
4448 /* Not sure if there is any point in this. */
4449 if (!NILP (Vw32_generate_fake_inodes
))
4450 fake_inode
= generate_inode_val (name
);
4451 else if (fake_inode
== 0)
4453 /* For want of something better, try to make everything unique. */
4454 static DWORD gen_num
= 0;
4455 fake_inode
= ++gen_num
;
4459 buf
->st_ino
= fake_inode
;
4461 buf
->st_dev
= serialnum
;
4462 buf
->st_rdev
= serialnum
;
4464 buf
->st_size
= fs_high
;
4465 buf
->st_size
<<= 32;
4466 buf
->st_size
+= fs_low
;
4467 buf
->st_nlink
= nlinks
;
4469 /* Convert timestamps to Unix format. */
4470 buf
->st_mtime
= convert_time (wtime
);
4471 buf
->st_atime
= convert_time (atime
);
4472 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4473 buf
->st_ctime
= convert_time (ctime
);
4474 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4476 /* determine rwx permissions */
4477 if (is_a_symlink
&& !follow_symlinks
)
4478 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
4481 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
4482 permission
= S_IREAD
;
4484 permission
= S_IREAD
| S_IWRITE
;
4486 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4487 permission
|= S_IEXEC
;
4488 else if (is_exec (name
))
4489 permission
|= S_IEXEC
;
4492 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
4498 stat (const char * path
, struct stat
* buf
)
4500 return stat_worker (path
, buf
, 1);
4504 lstat (const char * path
, struct stat
* buf
)
4506 return stat_worker (path
, buf
, 0);
4510 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
4512 /* Rely on a hack: an open directory is modeled as file descriptor 0.
4513 This is good enough for the current usage in Emacs, but is fragile.
4515 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
4516 Gnulib does this and can serve as a model. */
4517 char fullname
[MAX_PATH
];
4521 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
4524 errno
= ENAMETOOLONG
;
4530 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
4533 /* Provide fstat and utime as well as stat for consistent handling of
4536 fstat (int desc
, struct stat
* buf
)
4538 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
4539 BY_HANDLE_FILE_INFORMATION info
;
4540 unsigned __int64 fake_inode
;
4543 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
4545 case FILE_TYPE_DISK
:
4546 buf
->st_mode
= S_IFREG
;
4547 if (!GetFileInformationByHandle (fh
, &info
))
4553 case FILE_TYPE_PIPE
:
4554 buf
->st_mode
= S_IFIFO
;
4556 case FILE_TYPE_CHAR
:
4557 case FILE_TYPE_UNKNOWN
:
4559 buf
->st_mode
= S_IFCHR
;
4561 memset (&info
, 0, sizeof (info
));
4562 info
.dwFileAttributes
= 0;
4563 info
.ftCreationTime
= utc_base_ft
;
4564 info
.ftLastAccessTime
= utc_base_ft
;
4565 info
.ftLastWriteTime
= utc_base_ft
;
4568 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
4569 buf
->st_mode
= S_IFDIR
;
4571 buf
->st_nlink
= info
.nNumberOfLinks
;
4572 /* Might as well use file index to fake inode values, but this
4573 is not guaranteed to be unique unless we keep a handle open
4574 all the time (even then there are situations where it is
4575 not unique). Reputedly, there are at most 48 bits of info
4576 (on NTFS, presumably less on FAT). */
4577 fake_inode
= info
.nFileIndexHigh
;
4579 fake_inode
+= info
.nFileIndexLow
;
4581 /* MSVC defines _ino_t to be short; other libc's might not. */
4582 if (sizeof (buf
->st_ino
) == 2)
4583 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
4585 buf
->st_ino
= fake_inode
;
4587 /* If the caller so requested, get the true file owner and group.
4588 Otherwise, consider the file to belong to the current user. */
4589 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4590 get_file_owner_and_group (NULL
, buf
);
4593 PSECURITY_DESCRIPTOR psd
= NULL
;
4595 psd
= get_file_security_desc_by_handle (fh
);
4598 get_file_owner_and_group (psd
, buf
);
4602 get_file_owner_and_group (NULL
, buf
);
4605 buf
->st_dev
= info
.dwVolumeSerialNumber
;
4606 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
4608 buf
->st_size
= info
.nFileSizeHigh
;
4609 buf
->st_size
<<= 32;
4610 buf
->st_size
+= info
.nFileSizeLow
;
4612 /* Convert timestamps to Unix format. */
4613 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
4614 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
4615 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
4616 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
4617 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
4619 /* determine rwx permissions */
4620 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
4621 permission
= S_IREAD
;
4623 permission
= S_IREAD
| S_IWRITE
;
4625 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
4626 permission
|= S_IEXEC
;
4629 #if 0 /* no way of knowing the filename */
4630 char * p
= strrchr (name
, '.');
4632 (xstrcasecmp (p
, ".exe") == 0 ||
4633 xstrcasecmp (p
, ".com") == 0 ||
4634 xstrcasecmp (p
, ".bat") == 0 ||
4635 xstrcasecmp (p
, ".cmd") == 0))
4636 permission
|= S_IEXEC
;
4640 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
4645 /* A version of 'utime' which handles directories as well as
4649 utime (const char *name
, struct utimbuf
*times
)
4651 struct utimbuf deftime
;
4658 deftime
.modtime
= deftime
.actime
= time (NULL
);
4662 /* Need write access to set times. */
4663 fh
= CreateFile (name
, FILE_WRITE_ATTRIBUTES
,
4664 /* If NAME specifies a directory, FILE_SHARE_DELETE
4665 allows other processes to delete files inside it,
4666 while we have the directory open. */
4667 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
4668 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4669 if (fh
!= INVALID_HANDLE_VALUE
)
4671 convert_from_time_t (times
->actime
, &atime
);
4672 convert_from_time_t (times
->modtime
, &mtime
);
4673 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
4690 /* Symlink-related functions. */
4691 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
4692 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
4696 symlink (char const *filename
, char const *linkname
)
4698 char linkfn
[MAX_PATH
], *tgtfn
;
4700 int dir_access
, filename_ends_in_slash
;
4703 /* Diagnostics follows Posix as much as possible. */
4704 if (filename
== NULL
|| linkname
== NULL
)
4714 if (strlen (filename
) > MAX_PATH
|| strlen (linkname
) > MAX_PATH
)
4716 errno
= ENAMETOOLONG
;
4720 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
4721 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
4727 dbcs_p
= max_filename_mbslen () > 1;
4729 /* Note: since empty FILENAME was already rejected, we can safely
4730 refer to FILENAME[1]. */
4731 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
4733 /* Non-absolute FILENAME is understood as being relative to
4734 LINKNAME's directory. We need to prepend that directory to
4735 FILENAME to get correct results from faccessat below, since
4736 otherwise it will interpret FILENAME relative to the
4737 directory where the Emacs process runs. Note that
4738 make-symbolic-link always makes sure LINKNAME is a fully
4739 expanded file name. */
4741 char *p
= linkfn
+ strlen (linkfn
);
4745 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
4750 char *p1
= CharPrevExA (file_name_codepage
, linkfn
, p
, 0);
4752 while (p
> linkfn
&& !IS_ANY_SEP (*p1
))
4755 p1
= CharPrevExA (file_name_codepage
, linkfn
, p1
, 0);
4759 strncpy (tem
, linkfn
, p
- linkfn
);
4760 tem
[p
- linkfn
] = '\0';
4761 strcat (tem
, filename
);
4762 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
4765 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
4767 /* Since Windows distinguishes between symlinks to directories and
4768 to files, we provide a kludgy feature: if FILENAME doesn't
4769 exist, but ends in a slash, we create a symlink to directory. If
4770 FILENAME exists and is a directory, we always create a symlink to
4773 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
4776 const char *end
= filename
+ strlen (filename
);
4777 const char *n
= CharPrevExA (file_name_codepage
, filename
, end
, 0);
4779 filename_ends_in_slash
= IS_DIRECTORY_SEP (*n
);
4781 if (dir_access
== 0 || filename_ends_in_slash
)
4782 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
4784 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
4785 if (filename_ends_in_slash
)
4786 tgtfn
[strlen (tgtfn
) - 1] = '\0';
4789 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
4791 /* ENOSYS is set by create_symbolic_link, when it detects that
4792 the OS doesn't support the CreateSymbolicLink API. */
4793 if (errno
!= ENOSYS
)
4795 DWORD w32err
= GetLastError ();
4799 /* ERROR_SUCCESS is sometimes returned when LINKFN and
4800 TGTFN point to the same file name, go figure. */
4802 case ERROR_FILE_EXISTS
:
4805 case ERROR_ACCESS_DENIED
:
4808 case ERROR_FILE_NOT_FOUND
:
4809 case ERROR_PATH_NOT_FOUND
:
4810 case ERROR_BAD_NETPATH
:
4811 case ERROR_INVALID_REPARSE_DATA
:
4814 case ERROR_DIRECTORY
:
4817 case ERROR_PRIVILEGE_NOT_HELD
:
4818 case ERROR_NOT_ALL_ASSIGNED
:
4821 case ERROR_DISK_FULL
:
4834 /* A quick inexpensive test of whether FILENAME identifies a file that
4835 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
4836 must already be in the normalized form returned by
4839 Note: for repeated operations on many files, it is best to test
4840 whether the underlying volume actually supports symlinks, by
4841 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
4842 avoid the call to this function if it doesn't. That's because the
4843 call to GetFileAttributes takes a non-negligible time, especially
4844 on non-local or removable filesystems. See stat_worker for an
4845 example of how to do that. */
4847 is_symlink (const char *filename
)
4850 WIN32_FIND_DATA wfd
;
4853 attrs
= GetFileAttributes (filename
);
4856 DWORD w32err
= GetLastError ();
4860 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
4862 case ERROR_ACCESS_DENIED
:
4865 case ERROR_FILE_NOT_FOUND
:
4866 case ERROR_PATH_NOT_FOUND
:
4873 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
4875 logon_network_drive (filename
);
4876 fh
= FindFirstFile (filename
, &wfd
);
4877 if (fh
== INVALID_HANDLE_VALUE
)
4880 return (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
4881 && (wfd
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
4884 /* If NAME identifies a symbolic link, copy into BUF the file name of
4885 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
4886 null-terminate the target name, even if it fits. Return the number
4887 of bytes copied, or -1 if NAME is not a symlink or any error was
4888 encountered while resolving it. The file name copied into BUF is
4889 encoded in the current ANSI codepage. */
4891 readlink (const char *name
, char *buf
, size_t buf_size
)
4894 TOKEN_PRIVILEGES privs
;
4895 int restore_privs
= 0;
4910 path
= map_w32_filename (name
, NULL
);
4912 if (strlen (path
) > MAX_PATH
)
4914 errno
= ENAMETOOLONG
;
4919 if (is_windows_9x () == TRUE
4920 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
4921 || !is_symlink (path
))
4924 errno
= EINVAL
; /* not a symlink */
4928 /* Done with simple tests, now we're in for some _real_ work. */
4929 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
4931 /* Implementation note: From here and onward, don't return early,
4932 since that will fail to restore the original set of privileges of
4933 the calling thread. */
4935 retval
= -1; /* not too optimistic, are we? */
4937 /* Note: In the next call to CreateFile, we use zero as the 2nd
4938 argument because, when the symlink is a hidden/system file,
4939 e.g. 'C:\Users\All Users', GENERIC_READ fails with
4940 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
4941 and directory symlinks. */
4942 sh
= CreateFile (path
, 0, 0, NULL
, OPEN_EXISTING
,
4943 FILE_FLAG_OPEN_REPARSE_POINT
| FILE_FLAG_BACKUP_SEMANTICS
,
4945 if (sh
!= INVALID_HANDLE_VALUE
)
4947 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
4948 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
4951 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
4952 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
4955 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
4959 /* Copy the link target name, in wide characters, from
4960 reparse_data, then convert it to multibyte encoding in
4961 the current locale's codepage. */
4963 BYTE lname
[MAX_PATH
];
4966 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
4968 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
4969 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
4970 /* This updates file_name_codepage which we need below. */
4971 int dbcs_p
= max_filename_mbslen () > 1;
4973 /* According to MSDN, PrintNameLength does not include the
4974 terminating null character. */
4975 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
4976 memcpy (lwname
, lwname_src
, lwname_len
);
4977 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
4979 lname_len
= WideCharToMultiByte (file_name_codepage
, 0, lwname
, -1,
4980 lname
, MAX_PATH
, NULL
, NULL
);
4983 /* WideCharToMultiByte failed. */
4984 DWORD w32err1
= GetLastError ();
4988 case ERROR_INSUFFICIENT_BUFFER
:
4989 errno
= ENAMETOOLONG
;
4991 case ERROR_INVALID_PARAMETER
:
4994 case ERROR_NO_UNICODE_TRANSLATION
:
5004 size_t size_to_copy
= buf_size
;
5005 BYTE
*p
= lname
, *p2
;
5006 BYTE
*pend
= p
+ lname_len
;
5008 /* Normalize like dostounix_filename does, but we don't
5009 want to assume that lname is null-terminated. */
5011 p2
= CharNextExA (file_name_codepage
, p
, 0);
5014 if (*p
&& *p2
== ':' && *p
>= 'A' && *p
<= 'Z')
5025 p
= CharNextExA (file_name_codepage
, p
, 0);
5026 /* CharNextExA doesn't advance at null character. */
5033 /* Testing for null-terminated LNAME is paranoia:
5034 WideCharToMultiByte should always return a
5035 null-terminated string when its 4th argument is -1
5036 and its 3rd argument is null-terminated (which they
5038 if (lname
[lname_len
- 1] == '\0')
5040 if (lname_len
<= buf_size
)
5041 size_to_copy
= lname_len
;
5042 strncpy (buf
, lname
, size_to_copy
);
5044 retval
= size_to_copy
;
5051 /* CreateFile failed. */
5052 DWORD w32err2
= GetLastError ();
5056 case ERROR_FILE_NOT_FOUND
:
5057 case ERROR_PATH_NOT_FOUND
:
5060 case ERROR_ACCESS_DENIED
:
5061 case ERROR_TOO_MANY_OPEN_FILES
:
5071 restore_privilege (&privs
);
5079 readlinkat (int fd
, char const *name
, char *buffer
,
5082 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5083 as in fstatat. FIXME: Add proper support for readlinkat. */
5084 char fullname
[MAX_PATH
];
5088 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5091 errno
= ENAMETOOLONG
;
5097 return readlink (name
, buffer
, buffer_size
);
5100 /* If FILE is a symlink, return its target (stored in a static
5101 buffer); otherwise return FILE.
5103 This function repeatedly resolves symlinks in the last component of
5104 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5105 until it arrives at a file whose last component is not a symlink,
5106 or some error occurs. It returns the target of the last
5107 successfully resolved symlink in the chain. If it succeeds to
5108 resolve even a single symlink, the value returned is an absolute
5109 file name with backslashes (result of GetFullPathName). By
5110 contrast, if the original FILE is returned, it is unaltered.
5112 Note: This function can set errno even if it succeeds.
5114 Implementation note: we only resolve the last portion ("basename")
5115 of the argument FILE and of each following file in the chain,
5116 disregarding any possible symlinks in its leading directories.
5117 This is because Windows system calls and library functions
5118 transparently resolve symlinks in leading directories and return
5119 correct information, as long as the basename is not a symlink. */
5121 chase_symlinks (const char *file
)
5123 static char target
[MAX_PATH
];
5124 char link
[MAX_PATH
];
5125 ssize_t res
, link_len
;
5129 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5130 return (char *)file
;
5132 if ((link_len
= GetFullPathName (file
, MAX_PATH
, link
, NULL
)) == 0)
5133 return (char *)file
;
5135 dbcs_p
= max_filename_mbslen () > 1;
5139 /* Remove trailing slashes, as we want to resolve the last
5140 non-trivial part of the link name. */
5143 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5144 link
[link_len
--] = '\0';
5146 else if (link_len
> 3)
5148 char *n
= CharPrevExA (file_name_codepage
, link
, link
+ link_len
, 0);
5150 while (n
>= link
+ 2 && IS_DIRECTORY_SEP (*n
))
5153 n
= CharPrevExA (file_name_codepage
, link
, n
, 0);
5157 res
= readlink (link
, target
, MAX_PATH
);
5161 if (!(IS_DEVICE_SEP (target
[1])
5162 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5164 /* Target is relative. Append it to the directory part of
5165 the symlink, then copy the result back to target. */
5166 char *p
= link
+ link_len
;
5170 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5175 char *p1
= CharPrevExA (file_name_codepage
, link
, p
, 0);
5177 while (p
> link
&& !IS_ANY_SEP (*p1
))
5180 p1
= CharPrevExA (file_name_codepage
, link
, p1
, 0);
5184 strcpy (target
, link
);
5186 /* Resolve any "." and ".." to get a fully-qualified file name
5188 link_len
= GetFullPathName (target
, MAX_PATH
, link
, NULL
);
5190 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5192 if (loop_count
> 100)
5195 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5196 return (char *)file
;
5201 /* Posix ACL emulation. */
5204 acl_valid (acl_t acl
)
5206 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5210 acl_to_text (acl_t acl
, ssize_t
*size
)
5213 SECURITY_INFORMATION flags
=
5214 OWNER_SECURITY_INFORMATION
|
5215 GROUP_SECURITY_INFORMATION
|
5216 DACL_SECURITY_INFORMATION
;
5217 char *retval
= NULL
;
5223 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5226 /* We don't want to mix heaps, so we duplicate the string in our
5227 heap and free the one allocated by the API. */
5228 retval
= xstrdup (str_acl
);
5231 LocalFree (str_acl
);
5233 else if (errno
!= ENOTSUP
)
5240 acl_from_text (const char *acl_str
)
5242 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5248 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5251 retval
= xmalloc (sd_size
);
5252 memcpy (retval
, psd
, sd_size
);
5255 else if (errno
!= ENOTSUP
)
5262 acl_free (void *ptr
)
5269 acl_get_file (const char *fname
, acl_type_t type
)
5271 PSECURITY_DESCRIPTOR psd
= NULL
;
5272 const char *filename
;
5274 if (type
== ACL_TYPE_ACCESS
)
5277 SECURITY_INFORMATION si
=
5278 OWNER_SECURITY_INFORMATION
|
5279 GROUP_SECURITY_INFORMATION
|
5280 DACL_SECURITY_INFORMATION
;
5283 filename
= map_w32_filename (fname
, NULL
);
5284 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5285 fname
= chase_symlinks (filename
);
5290 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5291 && errno
!= ENOTSUP
)
5293 err
= GetLastError ();
5294 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5296 psd
= xmalloc (sd_len
);
5297 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5304 else if (err
== ERROR_FILE_NOT_FOUND
5305 || err
== ERROR_PATH_NOT_FOUND
)
5313 else if (type
!= ACL_TYPE_DEFAULT
)
5320 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5322 TOKEN_PRIVILEGES old1
, old2
;
5324 int st
= 0, retval
= -1;
5325 SECURITY_INFORMATION flags
= 0;
5331 const char *filename
;
5333 if (acl_valid (acl
) != 0
5334 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5340 if (type
== ACL_TYPE_DEFAULT
)
5346 filename
= map_w32_filename (fname
, NULL
);
5347 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5348 fname
= chase_symlinks (filename
);
5352 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5354 flags
|= OWNER_SECURITY_INFORMATION
;
5355 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5357 flags
|= GROUP_SECURITY_INFORMATION
;
5358 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5361 flags
|= DACL_SECURITY_INFORMATION
;
5365 /* According to KB-245153, setting the owner will succeed if either:
5366 (1) the caller is the user who will be the new owner, and has the
5367 SE_TAKE_OWNERSHIP privilege, or
5368 (2) the caller has the SE_RESTORE privilege, in which case she can
5369 set any valid user or group as the owner
5371 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5372 privileges, and disregard any failures in obtaining them. If
5373 these privileges cannot be obtained, and do not already exist in
5374 the calling thread's security token, this function could fail
5376 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5378 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5383 if (!set_file_security ((char *)fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5385 err
= GetLastError ();
5387 if (errno
== ENOTSUP
)
5389 else if (err
== ERROR_INVALID_OWNER
5390 || err
== ERROR_NOT_ALL_ASSIGNED
5391 || err
== ERROR_ACCESS_DENIED
)
5393 /* Maybe the requested ACL and the one the file already has
5394 are identical, in which case we can silently ignore the
5395 failure. (And no, Windows doesn't.) */
5396 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5401 char *acl_from
= acl_to_text (current_acl
, NULL
);
5402 char *acl_to
= acl_to_text (acl
, NULL
);
5404 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5410 acl_free (acl_from
);
5413 acl_free (current_acl
);
5416 else if (err
== ERROR_FILE_NOT_FOUND
|| err
== ERROR_PATH_NOT_FOUND
)
5430 restore_privilege (&old2
);
5431 restore_privilege (&old1
);
5439 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5440 have a fixed max size for file names, so we don't need the kind of
5441 alloc/malloc/realloc dance the gnulib version does. We also don't
5442 support FD-relative symlinks. */
5444 careadlinkat (int fd
, char const *filename
,
5445 char *buffer
, size_t buffer_size
,
5446 struct allocator
const *alloc
,
5447 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
5449 char linkname
[MAX_PATH
];
5452 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
5456 char *retval
= buffer
;
5458 linkname
[link_size
++] = '\0';
5459 if (link_size
> buffer_size
)
5460 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
5462 memcpy (retval
, linkname
, link_size
);
5470 /* Support for browsing other processes and their attributes. See
5471 process.c for the Lisp bindings. */
5473 /* Helper wrapper functions. */
5475 static HANDLE WINAPI
5476 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
5478 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
5480 if (g_b_init_create_toolhelp32_snapshot
== 0)
5482 g_b_init_create_toolhelp32_snapshot
= 1;
5483 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
5484 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5485 "CreateToolhelp32Snapshot");
5487 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
5489 return INVALID_HANDLE_VALUE
;
5491 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
5495 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
5497 static Process32First_Proc s_pfn_Process32_First
= NULL
;
5499 if (g_b_init_process32_first
== 0)
5501 g_b_init_process32_first
= 1;
5502 s_pfn_Process32_First
= (Process32First_Proc
)
5503 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5506 if (s_pfn_Process32_First
== NULL
)
5510 return (s_pfn_Process32_First (hSnapshot
, lppe
));
5514 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
5516 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
5518 if (g_b_init_process32_next
== 0)
5520 g_b_init_process32_next
= 1;
5521 s_pfn_Process32_Next
= (Process32Next_Proc
)
5522 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5525 if (s_pfn_Process32_Next
== NULL
)
5529 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
5533 open_thread_token (HANDLE ThreadHandle
,
5534 DWORD DesiredAccess
,
5536 PHANDLE TokenHandle
)
5538 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
5539 HMODULE hm_advapi32
= NULL
;
5540 if (is_windows_9x () == TRUE
)
5542 SetLastError (ERROR_NOT_SUPPORTED
);
5545 if (g_b_init_open_thread_token
== 0)
5547 g_b_init_open_thread_token
= 1;
5548 hm_advapi32
= LoadLibrary ("Advapi32.dll");
5549 s_pfn_Open_Thread_Token
=
5550 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
5552 if (s_pfn_Open_Thread_Token
== NULL
)
5554 SetLastError (ERROR_NOT_SUPPORTED
);
5558 s_pfn_Open_Thread_Token (
5567 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
5569 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
5570 HMODULE hm_advapi32
= NULL
;
5571 if (is_windows_9x () == TRUE
)
5575 if (g_b_init_impersonate_self
== 0)
5577 g_b_init_impersonate_self
= 1;
5578 hm_advapi32
= LoadLibrary ("Advapi32.dll");
5579 s_pfn_Impersonate_Self
=
5580 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
5582 if (s_pfn_Impersonate_Self
== NULL
)
5586 return s_pfn_Impersonate_Self (ImpersonationLevel
);
5590 revert_to_self (void)
5592 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
5593 HMODULE hm_advapi32
= NULL
;
5594 if (is_windows_9x () == TRUE
)
5598 if (g_b_init_revert_to_self
== 0)
5600 g_b_init_revert_to_self
= 1;
5601 hm_advapi32
= LoadLibrary ("Advapi32.dll");
5602 s_pfn_Revert_To_Self
=
5603 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
5605 if (s_pfn_Revert_To_Self
== NULL
)
5609 return s_pfn_Revert_To_Self ();
5613 get_process_memory_info (HANDLE h_proc
,
5614 PPROCESS_MEMORY_COUNTERS mem_counters
,
5617 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
5618 HMODULE hm_psapi
= NULL
;
5619 if (is_windows_9x () == TRUE
)
5623 if (g_b_init_get_process_memory_info
== 0)
5625 g_b_init_get_process_memory_info
= 1;
5626 hm_psapi
= LoadLibrary ("Psapi.dll");
5628 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
5629 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
5631 if (s_pfn_Get_Process_Memory_Info
== NULL
)
5635 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
5639 get_process_working_set_size (HANDLE h_proc
,
5643 static GetProcessWorkingSetSize_Proc
5644 s_pfn_Get_Process_Working_Set_Size
= NULL
;
5646 if (is_windows_9x () == TRUE
)
5650 if (g_b_init_get_process_working_set_size
== 0)
5652 g_b_init_get_process_working_set_size
= 1;
5653 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
5654 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5655 "GetProcessWorkingSetSize");
5657 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
5661 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
5665 global_memory_status (MEMORYSTATUS
*buf
)
5667 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
5669 if (is_windows_9x () == TRUE
)
5673 if (g_b_init_global_memory_status
== 0)
5675 g_b_init_global_memory_status
= 1;
5676 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
5677 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5678 "GlobalMemoryStatus");
5680 if (s_pfn_Global_Memory_Status
== NULL
)
5684 return s_pfn_Global_Memory_Status (buf
);
5688 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
5690 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
5692 if (is_windows_9x () == TRUE
)
5696 if (g_b_init_global_memory_status_ex
== 0)
5698 g_b_init_global_memory_status_ex
= 1;
5699 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
5700 GetProcAddress (GetModuleHandle ("kernel32.dll"),
5701 "GlobalMemoryStatusEx");
5703 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
5707 return s_pfn_Global_Memory_Status_Ex (buf
);
5711 list_system_processes (void)
5713 struct gcpro gcpro1
;
5714 Lisp_Object proclist
= Qnil
;
5717 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
5719 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
5721 PROCESSENTRY32 proc_entry
;
5727 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
5728 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
5729 res
= process32_next (h_snapshot
, &proc_entry
))
5731 proc_id
= proc_entry
.th32ProcessID
;
5732 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
5735 CloseHandle (h_snapshot
);
5737 proclist
= Fnreverse (proclist
);
5744 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
5746 TOKEN_PRIVILEGES priv
;
5747 DWORD priv_size
= sizeof (priv
);
5748 DWORD opriv_size
= sizeof (*old_priv
);
5749 HANDLE h_token
= NULL
;
5750 HANDLE h_thread
= GetCurrentThread ();
5754 res
= open_thread_token (h_thread
,
5755 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
5757 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
5759 if (impersonate_self (SecurityImpersonation
))
5760 res
= open_thread_token (h_thread
,
5761 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
5766 priv
.PrivilegeCount
= 1;
5767 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
5768 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
5769 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
5770 old_priv
, &opriv_size
)
5771 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
5775 CloseHandle (h_token
);
5781 restore_privilege (TOKEN_PRIVILEGES
*priv
)
5783 DWORD priv_size
= sizeof (*priv
);
5784 HANDLE h_token
= NULL
;
5787 if (open_thread_token (GetCurrentThread (),
5788 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
5791 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
5792 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
5796 CloseHandle (h_token
);
5802 ltime (ULONGLONG time_100ns
)
5804 ULONGLONG time_sec
= time_100ns
/ 10000000;
5805 int subsec
= time_100ns
% 10000000;
5806 return list4i (time_sec
>> 16, time_sec
& 0xffff,
5807 subsec
/ 10, subsec
% 10 * 100000);
5810 #define U64_TO_LISP_TIME(time) ltime (time)
5813 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
5814 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
5817 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
5818 ULONGLONG tem1
, tem2
, tem3
, tem
;
5821 || !get_process_times_fn
5822 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
5823 &ft_kernel
, &ft_user
))
5826 GetSystemTimeAsFileTime (&ft_current
);
5828 FILETIME_TO_U64 (tem1
, ft_kernel
);
5829 *stime
= U64_TO_LISP_TIME (tem1
);
5831 FILETIME_TO_U64 (tem2
, ft_user
);
5832 *utime
= U64_TO_LISP_TIME (tem2
);
5835 *ttime
= U64_TO_LISP_TIME (tem3
);
5837 FILETIME_TO_U64 (tem
, ft_creation
);
5838 /* Process no 4 (System) returns zero creation time. */
5841 *ctime
= U64_TO_LISP_TIME (tem
);
5845 FILETIME_TO_U64 (tem3
, ft_current
);
5846 tem
= (tem3
- utc_base
) - tem
;
5848 *etime
= U64_TO_LISP_TIME (tem
);
5852 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
5863 system_process_attributes (Lisp_Object pid
)
5865 struct gcpro gcpro1
, gcpro2
, gcpro3
;
5866 Lisp_Object attrs
= Qnil
;
5867 Lisp_Object cmd_str
, decoded_cmd
, tem
;
5868 HANDLE h_snapshot
, h_proc
;
5871 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
5872 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
5873 DWORD glength
= sizeof (gname
);
5874 HANDLE token
= NULL
;
5875 SID_NAME_USE user_type
;
5876 unsigned char *buf
= NULL
;
5878 TOKEN_USER user_token
;
5879 TOKEN_PRIMARY_GROUP group_token
;
5882 PROCESS_MEMORY_COUNTERS mem
;
5883 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
5884 SIZE_T minrss
, maxrss
;
5886 MEMORY_STATUS_EX memstex
;
5887 double totphys
= 0.0;
5888 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
5890 BOOL result
= FALSE
;
5892 CHECK_NUMBER_OR_FLOAT (pid
);
5893 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
5895 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
5897 GCPRO3 (attrs
, decoded_cmd
, tem
);
5899 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
5904 pe
.dwSize
= sizeof (PROCESSENTRY32
);
5905 for (res
= process32_first (h_snapshot
, &pe
); res
;
5906 res
= process32_next (h_snapshot
, &pe
))
5908 if (proc_id
== pe
.th32ProcessID
)
5911 decoded_cmd
= build_string ("Idle");
5914 /* Decode the command name from locale-specific
5916 cmd_str
= build_unibyte_string (pe
.szExeFile
);
5919 code_convert_string_norecord (cmd_str
,
5920 Vlocale_coding_system
, 0);
5922 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
5923 attrs
= Fcons (Fcons (Qppid
,
5924 make_fixnum_or_float (pe
.th32ParentProcessID
)),
5926 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
5928 attrs
= Fcons (Fcons (Qthcount
,
5929 make_fixnum_or_float (pe
.cntThreads
)),
5936 CloseHandle (h_snapshot
);
5945 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
5947 /* If we were denied a handle to the process, try again after
5948 enabling the SeDebugPrivilege in our process. */
5951 TOKEN_PRIVILEGES priv_current
;
5953 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
5955 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
5957 restore_privilege (&priv_current
);
5963 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
5966 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
5967 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
5969 buf
= xmalloc (blen
);
5970 result
= get_token_information (token
, TokenUser
,
5971 (LPVOID
)buf
, blen
, &needed
);
5974 memcpy (&user_token
, buf
, sizeof (user_token
));
5975 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
5977 euid
= get_rid (user_token
.User
.Sid
);
5978 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
5983 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
5986 strcpy (uname
, "unknown");
5990 ulength
= strlen (uname
);
5996 /* Determine a reasonable euid and gid values. */
5997 if (xstrcasecmp ("administrator", uname
) == 0)
5999 euid
= 500; /* well-known Administrator uid */
6000 egid
= 513; /* well-known None gid */
6004 /* Get group id and name. */
6005 result
= get_token_information (token
, TokenPrimaryGroup
,
6006 (LPVOID
)buf
, blen
, &needed
);
6007 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6009 buf
= xrealloc (buf
, blen
= needed
);
6010 result
= get_token_information (token
, TokenPrimaryGroup
,
6011 (LPVOID
)buf
, blen
, &needed
);
6015 memcpy (&group_token
, buf
, sizeof (group_token
));
6016 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6018 egid
= get_rid (group_token
.PrimaryGroup
);
6019 dlength
= sizeof (domain
);
6021 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6022 gname
, &glength
, NULL
, &dlength
,
6025 w32_add_to_cache (group_token
.PrimaryGroup
,
6029 strcpy (gname
, "None");
6033 glength
= strlen (gname
);
6041 if (!is_windows_9x ())
6043 /* We couldn't open the process token, presumably because of
6044 insufficient access rights. Assume this process is run
6046 strcpy (uname
, "SYSTEM");
6047 strcpy (gname
, "None");
6048 euid
= 18; /* SYSTEM */
6049 egid
= 513; /* None */
6050 glength
= strlen (gname
);
6051 ulength
= strlen (uname
);
6053 /* If we are running under Windows 9X, where security calls are
6054 not supported, we assume all processes are run by the current
6056 else if (GetUserName (uname
, &ulength
))
6058 if (xstrcasecmp ("administrator", uname
) == 0)
6063 strcpy (gname
, "None");
6064 glength
= strlen (gname
);
6065 ulength
= strlen (uname
);
6071 strcpy (uname
, "administrator");
6072 ulength
= strlen (uname
);
6073 strcpy (gname
, "None");
6074 glength
= strlen (gname
);
6077 CloseHandle (token
);
6080 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6081 tem
= make_unibyte_string (uname
, ulength
);
6082 attrs
= Fcons (Fcons (Quser
,
6083 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6085 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6086 tem
= make_unibyte_string (gname
, glength
);
6087 attrs
= Fcons (Fcons (Qgroup
,
6088 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6091 if (global_memory_status_ex (&memstex
))
6092 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6093 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6095 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6096 double, so we need to do this for it... */
6098 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6099 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6100 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6102 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6104 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6105 else if (global_memory_status (&memst
))
6106 totphys
= memst
.dwTotalPhys
/ 1024.0;
6109 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6112 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6114 attrs
= Fcons (Fcons (Qmajflt
,
6115 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6117 attrs
= Fcons (Fcons (Qvsize
,
6118 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6120 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6122 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6125 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6127 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6129 attrs
= Fcons (Fcons (Qmajflt
,
6130 make_fixnum_or_float (mem
.PageFaultCount
)),
6132 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6134 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6137 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6139 DWORD rss
= maxrss
/ 1024;
6141 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6143 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6146 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6148 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6149 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6150 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6151 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6152 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6153 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6156 /* FIXME: Retrieve command line by walking the PEB of the process. */
6159 CloseHandle (h_proc
);
6165 /* Wrappers for winsock functions to map between our file descriptors
6166 and winsock's handles; also set h_errno for convenience.
6168 To allow Emacs to run on systems which don't have winsock support
6169 installed, we dynamically link to winsock on startup if present, and
6170 otherwise provide the minimum necessary functionality
6171 (eg. gethostname). */
6173 /* function pointers for relevant socket functions */
6174 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6175 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6176 int (PASCAL
*pfn_WSAGetLastError
) (void);
6177 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6178 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6179 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6180 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6181 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6182 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6183 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6184 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6185 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6186 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6187 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6188 int (PASCAL
*pfn_WSACleanup
) (void);
6190 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6191 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6192 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6193 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6194 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6195 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6196 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6197 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6198 const char * optval
, int optlen
);
6199 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6200 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6202 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6203 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6204 struct sockaddr
* from
, int * fromlen
);
6205 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6206 const struct sockaddr
* to
, int tolen
);
6208 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6209 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6210 #ifndef HANDLE_FLAG_INHERIT
6211 #define HANDLE_FLAG_INHERIT 1
6215 static int winsock_inuse
;
6220 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6222 release_listen_threads ();
6223 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6224 after WSAStartup returns successfully, but it seems reasonable
6225 to allow unloading winsock anyway in that case. */
6226 if (pfn_WSACleanup () == 0 ||
6227 pfn_WSAGetLastError () == WSAENETDOWN
)
6229 if (FreeLibrary (winsock_lib
))
6238 init_winsock (int load_now
)
6240 WSADATA winsockData
;
6242 if (winsock_lib
!= NULL
)
6245 pfn_SetHandleInformation
6246 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6247 "SetHandleInformation");
6249 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6251 if (winsock_lib
!= NULL
)
6253 /* dynamically link to socket functions */
6255 #define LOAD_PROC(fn) \
6256 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6259 LOAD_PROC (WSAStartup
);
6260 LOAD_PROC (WSASetLastError
);
6261 LOAD_PROC (WSAGetLastError
);
6262 LOAD_PROC (WSAEventSelect
);
6263 LOAD_PROC (WSACreateEvent
);
6264 LOAD_PROC (WSACloseEvent
);
6267 LOAD_PROC (connect
);
6268 LOAD_PROC (ioctlsocket
);
6271 LOAD_PROC (closesocket
);
6272 LOAD_PROC (shutdown
);
6275 LOAD_PROC (inet_addr
);
6276 LOAD_PROC (gethostname
);
6277 LOAD_PROC (gethostbyname
);
6278 LOAD_PROC (getservbyname
);
6279 LOAD_PROC (getpeername
);
6280 LOAD_PROC (WSACleanup
);
6281 LOAD_PROC (setsockopt
);
6283 LOAD_PROC (getsockname
);
6285 LOAD_PROC (recvfrom
);
6289 /* specify version 1.1 of winsock */
6290 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6292 if (winsockData
.wVersion
!= 0x101)
6297 /* Report that winsock exists and is usable, but leave
6298 socket functions disabled. I am assuming that calling
6299 WSAStartup does not require any network interaction,
6300 and in particular does not cause or require a dial-up
6301 connection to be established. */
6304 FreeLibrary (winsock_lib
);
6312 FreeLibrary (winsock_lib
);
6322 /* Function to map winsock error codes to errno codes for those errno
6323 code defined in errno.h (errno values not defined by errno.h are
6324 already in nt/inc/sys/socket.h). */
6331 if (winsock_lib
== NULL
)
6334 wsa_err
= pfn_WSAGetLastError ();
6338 case WSAEACCES
: errno
= EACCES
; break;
6339 case WSAEBADF
: errno
= EBADF
; break;
6340 case WSAEFAULT
: errno
= EFAULT
; break;
6341 case WSAEINTR
: errno
= EINTR
; break;
6342 case WSAEINVAL
: errno
= EINVAL
; break;
6343 case WSAEMFILE
: errno
= EMFILE
; break;
6344 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
6345 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
6346 default: errno
= wsa_err
; break;
6354 if (winsock_lib
!= NULL
)
6355 pfn_WSASetLastError (0);
6358 /* Extend strerror to handle the winsock-specific error codes. */
6362 } _wsa_errlist
[] = {
6363 {WSAEINTR
, "Interrupted function call"},
6364 {WSAEBADF
, "Bad file descriptor"},
6365 {WSAEACCES
, "Permission denied"},
6366 {WSAEFAULT
, "Bad address"},
6367 {WSAEINVAL
, "Invalid argument"},
6368 {WSAEMFILE
, "Too many open files"},
6370 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
6371 {WSAEINPROGRESS
, "Operation now in progress"},
6372 {WSAEALREADY
, "Operation already in progress"},
6373 {WSAENOTSOCK
, "Socket operation on non-socket"},
6374 {WSAEDESTADDRREQ
, "Destination address required"},
6375 {WSAEMSGSIZE
, "Message too long"},
6376 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
6377 {WSAENOPROTOOPT
, "Bad protocol option"},
6378 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
6379 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
6380 {WSAEOPNOTSUPP
, "Operation not supported"},
6381 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
6382 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
6383 {WSAEADDRINUSE
, "Address already in use"},
6384 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
6385 {WSAENETDOWN
, "Network is down"},
6386 {WSAENETUNREACH
, "Network is unreachable"},
6387 {WSAENETRESET
, "Network dropped connection on reset"},
6388 {WSAECONNABORTED
, "Software caused connection abort"},
6389 {WSAECONNRESET
, "Connection reset by peer"},
6390 {WSAENOBUFS
, "No buffer space available"},
6391 {WSAEISCONN
, "Socket is already connected"},
6392 {WSAENOTCONN
, "Socket is not connected"},
6393 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
6394 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
6395 {WSAETIMEDOUT
, "Connection timed out"},
6396 {WSAECONNREFUSED
, "Connection refused"},
6397 {WSAELOOP
, "Network loop"}, /* not sure */
6398 {WSAENAMETOOLONG
, "Name is too long"},
6399 {WSAEHOSTDOWN
, "Host is down"},
6400 {WSAEHOSTUNREACH
, "No route to host"},
6401 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
6402 {WSAEPROCLIM
, "Too many processes"},
6403 {WSAEUSERS
, "Too many users"}, /* not sure */
6404 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
6405 {WSAESTALE
, "Data is stale"}, /* not sure */
6406 {WSAEREMOTE
, "Remote error"}, /* not sure */
6408 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
6409 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
6410 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
6411 {WSAEDISCON
, "Graceful shutdown in progress"},
6413 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
6414 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
6415 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
6416 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
6417 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
6418 {WSASYSCALLFAILURE
, "System call failure"},
6419 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
6420 {WSATYPE_NOT_FOUND
, "Class type not found"},
6421 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
6422 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
6423 {WSAEREFUSED
, "Operation refused"}, /* not sure */
6426 {WSAHOST_NOT_FOUND
, "Host not found"},
6427 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
6428 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
6429 {WSANO_DATA
, "Valid name, no data record of requested type"},
6435 sys_strerror (int error_no
)
6438 static char unknown_msg
[40];
6440 if (error_no
>= 0 && error_no
< sys_nerr
)
6441 return sys_errlist
[error_no
];
6443 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
6444 if (_wsa_errlist
[i
].errnum
== error_no
)
6445 return _wsa_errlist
[i
].msg
;
6447 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
6451 /* [andrewi 3-May-96] I've had conflicting results using both methods,
6452 but I believe the method of keeping the socket handle separate (and
6453 insuring it is not inheritable) is the correct one. */
6455 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
6457 static int socket_to_fd (SOCKET s
);
6460 sys_socket (int af
, int type
, int protocol
)
6464 if (winsock_lib
== NULL
)
6467 return INVALID_SOCKET
;
6472 /* call the real socket function */
6473 s
= pfn_socket (af
, type
, protocol
);
6475 if (s
!= INVALID_SOCKET
)
6476 return socket_to_fd (s
);
6482 /* Convert a SOCKET to a file descriptor. */
6484 socket_to_fd (SOCKET s
)
6489 /* Although under NT 3.5 _open_osfhandle will accept a socket
6490 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
6491 that does not work under NT 3.1. However, we can get the same
6492 effect by using a backdoor function to replace an existing
6493 descriptor handle with the one we want. */
6495 /* allocate a file descriptor (with appropriate flags) */
6496 fd
= _open ("NUL:", _O_RDWR
);
6499 /* Make a non-inheritable copy of the socket handle. Note
6500 that it is possible that sockets aren't actually kernel
6501 handles, which appears to be the case on Windows 9x when
6502 the MS Proxy winsock client is installed. */
6504 /* Apparently there is a bug in NT 3.51 with some service
6505 packs, which prevents using DuplicateHandle to make a
6506 socket handle non-inheritable (causes WSACleanup to
6507 hang). The work-around is to use SetHandleInformation
6508 instead if it is available and implemented. */
6509 if (pfn_SetHandleInformation
)
6511 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
6515 HANDLE parent
= GetCurrentProcess ();
6516 HANDLE new_s
= INVALID_HANDLE_VALUE
;
6518 if (DuplicateHandle (parent
,
6524 DUPLICATE_SAME_ACCESS
))
6526 /* It is possible that DuplicateHandle succeeds even
6527 though the socket wasn't really a kernel handle,
6528 because a real handle has the same value. So
6529 test whether the new handle really is a socket. */
6530 long nonblocking
= 0;
6531 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
6533 pfn_closesocket (s
);
6538 CloseHandle (new_s
);
6543 eassert (fd
< MAXDESC
);
6544 fd_info
[fd
].hnd
= (HANDLE
) s
;
6546 /* set our own internal flags */
6547 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
6553 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
6555 /* attach child_process to fd_info */
6556 if (fd_info
[ fd
].cp
!= NULL
)
6558 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
6562 fd_info
[ fd
].cp
= cp
;
6565 winsock_inuse
++; /* count open sockets */
6573 pfn_closesocket (s
);
6579 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
6581 if (winsock_lib
== NULL
)
6584 return SOCKET_ERROR
;
6588 if (fd_info
[s
].flags
& FILE_SOCKET
)
6590 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
6591 if (rc
== SOCKET_ERROR
)
6596 return SOCKET_ERROR
;
6600 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
6602 if (winsock_lib
== NULL
)
6605 return SOCKET_ERROR
;
6609 if (fd_info
[s
].flags
& FILE_SOCKET
)
6611 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
6612 if (rc
== SOCKET_ERROR
)
6617 return SOCKET_ERROR
;
6621 sys_htons (u_short hostshort
)
6623 return (winsock_lib
!= NULL
) ?
6624 pfn_htons (hostshort
) : hostshort
;
6628 sys_ntohs (u_short netshort
)
6630 return (winsock_lib
!= NULL
) ?
6631 pfn_ntohs (netshort
) : netshort
;
6635 sys_inet_addr (const char * cp
)
6637 return (winsock_lib
!= NULL
) ?
6638 pfn_inet_addr (cp
) : INADDR_NONE
;
6642 sys_gethostname (char * name
, int namelen
)
6644 if (winsock_lib
!= NULL
)
6649 retval
= pfn_gethostname (name
, namelen
);
6650 if (retval
== SOCKET_ERROR
)
6655 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
6656 return !GetComputerName (name
, (DWORD
*)&namelen
);
6659 return SOCKET_ERROR
;
6663 sys_gethostbyname (const char * name
)
6665 struct hostent
* host
;
6666 int h_err
= h_errno
;
6668 if (winsock_lib
== NULL
)
6670 h_errno
= NO_RECOVERY
;
6676 host
= pfn_gethostbyname (name
);
6688 sys_getservbyname (const char * name
, const char * proto
)
6690 struct servent
* serv
;
6692 if (winsock_lib
== NULL
)
6699 serv
= pfn_getservbyname (name
, proto
);
6706 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
6708 if (winsock_lib
== NULL
)
6711 return SOCKET_ERROR
;
6715 if (fd_info
[s
].flags
& FILE_SOCKET
)
6717 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
6718 if (rc
== SOCKET_ERROR
)
6723 return SOCKET_ERROR
;
6727 sys_shutdown (int s
, int how
)
6729 if (winsock_lib
== NULL
)
6732 return SOCKET_ERROR
;
6736 if (fd_info
[s
].flags
& FILE_SOCKET
)
6738 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
6739 if (rc
== SOCKET_ERROR
)
6744 return SOCKET_ERROR
;
6748 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
6750 if (winsock_lib
== NULL
)
6753 return SOCKET_ERROR
;
6757 if (fd_info
[s
].flags
& FILE_SOCKET
)
6759 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
6760 (const char *)optval
, optlen
);
6761 if (rc
== SOCKET_ERROR
)
6766 return SOCKET_ERROR
;
6770 sys_listen (int s
, int backlog
)
6772 if (winsock_lib
== NULL
)
6775 return SOCKET_ERROR
;
6779 if (fd_info
[s
].flags
& FILE_SOCKET
)
6781 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
6782 if (rc
== SOCKET_ERROR
)
6785 fd_info
[s
].flags
|= FILE_LISTEN
;
6789 return SOCKET_ERROR
;
6793 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
6795 if (winsock_lib
== NULL
)
6798 return SOCKET_ERROR
;
6802 if (fd_info
[s
].flags
& FILE_SOCKET
)
6804 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
6805 if (rc
== SOCKET_ERROR
)
6810 return SOCKET_ERROR
;
6814 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
6816 if (winsock_lib
== NULL
)
6823 if (fd_info
[s
].flags
& FILE_LISTEN
)
6825 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
6827 if (t
== INVALID_SOCKET
)
6830 fd
= socket_to_fd (t
);
6834 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
6835 ResetEvent (fd_info
[s
].cp
->char_avail
);
6844 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
6845 struct sockaddr
* from
, int * fromlen
)
6847 if (winsock_lib
== NULL
)
6850 return SOCKET_ERROR
;
6854 if (fd_info
[s
].flags
& FILE_SOCKET
)
6856 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
6857 if (rc
== SOCKET_ERROR
)
6862 return SOCKET_ERROR
;
6866 sys_sendto (int s
, const char * buf
, int len
, int flags
,
6867 const struct sockaddr
* to
, int tolen
)
6869 if (winsock_lib
== NULL
)
6872 return SOCKET_ERROR
;
6876 if (fd_info
[s
].flags
& FILE_SOCKET
)
6878 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
6879 if (rc
== SOCKET_ERROR
)
6884 return SOCKET_ERROR
;
6887 /* Windows does not have an fcntl function. Provide an implementation
6888 good enough for Emacs. */
6890 fcntl (int s
, int cmd
, int options
)
6892 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
6893 invoked in a context where fd1 is closed and all descriptors less
6894 than fd1 are open, so sys_dup is an adequate implementation. */
6895 if (cmd
== F_DUPFD_CLOEXEC
)
6898 if (winsock_lib
== NULL
)
6905 if (fd_info
[s
].flags
& FILE_SOCKET
)
6907 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
6909 unsigned long nblock
= 1;
6910 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
6911 if (rc
== SOCKET_ERROR
)
6913 /* Keep track of the fact that we set this to non-blocking. */
6914 fd_info
[s
].flags
|= FILE_NDELAY
;
6920 return SOCKET_ERROR
;
6924 return SOCKET_ERROR
;
6928 /* Shadow main io functions: we need to handle pipes and sockets more
6929 intelligently, and implement non-blocking mode as well. */
6942 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
6944 child_process
* cp
= fd_info
[fd
].cp
;
6946 fd_info
[fd
].cp
= NULL
;
6948 if (CHILD_ACTIVE (cp
))
6950 /* if last descriptor to active child_process then cleanup */
6952 for (i
= 0; i
< MAXDESC
; i
++)
6956 if (fd_info
[i
].cp
== cp
)
6961 if (fd_info
[fd
].flags
& FILE_SOCKET
)
6963 if (winsock_lib
== NULL
) emacs_abort ();
6965 pfn_shutdown (SOCK_HANDLE (fd
), 2);
6966 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
6968 winsock_inuse
--; /* count open sockets */
6970 /* If the process handle is NULL, it's either a socket
6971 or serial connection, or a subprocess that was
6972 already reaped by reap_subprocess, but whose
6973 resources were not yet freed, because its output was
6974 not fully read yet by the time it was reaped. (This
6975 usually happens with async subprocesses whose output
6976 is being read by Emacs.) Otherwise, this process was
6977 not reaped yet, so we set its FD to a negative value
6978 to make sure sys_select will eventually get to
6979 calling the SIGCHLD handler for it, which will then
6980 invoke waitpid and reap_subprocess. */
6981 if (cp
->procinfo
.hProcess
== NULL
)
6989 if (fd
>= 0 && fd
< MAXDESC
)
6990 fd_info
[fd
].flags
= 0;
6992 /* Note that sockets do not need special treatment here (at least on
6993 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
6994 closesocket is equivalent to CloseHandle, which is to be expected
6995 because socket handles are fully fledged kernel handles. */
7007 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7009 /* duplicate our internal info as well */
7010 fd_info
[new_fd
] = fd_info
[fd
];
7016 sys_dup2 (int src
, int dst
)
7020 if (dst
< 0 || dst
>= MAXDESC
)
7026 /* make sure we close the destination first if it's a pipe or socket */
7027 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7030 rc
= _dup2 (src
, dst
);
7033 /* duplicate our internal info as well */
7034 fd_info
[dst
] = fd_info
[src
];
7040 pipe2 (int * phandles
, int pipe2_flags
)
7045 eassert (pipe2_flags
== O_CLOEXEC
);
7047 /* make pipe handles non-inheritable; when we spawn a child, we
7048 replace the relevant handle with an inheritable one. Also put
7049 pipes into binary mode; we will do text mode translation ourselves
7051 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7055 /* Protect against overflow, since Windows can open more handles than
7056 our fd_info array has room for. */
7057 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7059 _close (phandles
[0]);
7060 _close (phandles
[1]);
7066 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7067 fd_info
[phandles
[0]].flags
= flags
;
7069 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7070 fd_info
[phandles
[1]].flags
= flags
;
7077 /* Function to do blocking read of one byte, needed to implement
7078 select. It is only allowed on communication ports, sockets, or
7081 _sys_read_ahead (int fd
)
7086 if (fd
< 0 || fd
>= MAXDESC
)
7087 return STATUS_READ_ERROR
;
7089 cp
= fd_info
[fd
].cp
;
7091 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7092 return STATUS_READ_ERROR
;
7094 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7095 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7097 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7101 cp
->status
= STATUS_READ_IN_PROGRESS
;
7103 if (fd_info
[fd
].flags
& FILE_PIPE
)
7105 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7107 /* Give subprocess time to buffer some more output for us before
7108 reporting that input is available; we need this because Windows 95
7109 connects DOS programs to pipes by making the pipe appear to be
7110 the normal console stdout - as a result most DOS programs will
7111 write to stdout without buffering, ie. one character at a
7112 time. Even some W32 programs do this - "dir" in a command
7113 shell on NT is very slow if we don't do this. */
7116 int wait
= w32_pipe_read_delay
;
7122 /* Yield remainder of our time slice, effectively giving a
7123 temporary priority boost to the child process. */
7127 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7129 HANDLE hnd
= fd_info
[fd
].hnd
;
7130 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7133 /* Configure timeouts for blocking read. */
7134 if (!GetCommTimeouts (hnd
, &ct
))
7136 cp
->status
= STATUS_READ_ERROR
;
7137 return STATUS_READ_ERROR
;
7139 ct
.ReadIntervalTimeout
= 0;
7140 ct
.ReadTotalTimeoutMultiplier
= 0;
7141 ct
.ReadTotalTimeoutConstant
= 0;
7142 if (!SetCommTimeouts (hnd
, &ct
))
7144 cp
->status
= STATUS_READ_ERROR
;
7145 return STATUS_READ_ERROR
;
7148 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7150 if (GetLastError () != ERROR_IO_PENDING
)
7152 cp
->status
= STATUS_READ_ERROR
;
7153 return STATUS_READ_ERROR
;
7155 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7157 cp
->status
= STATUS_READ_ERROR
;
7158 return STATUS_READ_ERROR
;
7162 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7164 unsigned long nblock
= 0;
7165 /* We always want this to block, so temporarily disable NDELAY. */
7166 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7167 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7169 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7171 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7174 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7178 if (rc
== sizeof (char))
7179 cp
->status
= STATUS_READ_SUCCEEDED
;
7181 cp
->status
= STATUS_READ_FAILED
;
7187 _sys_wait_accept (int fd
)
7193 if (fd
< 0 || fd
>= MAXDESC
)
7194 return STATUS_READ_ERROR
;
7196 cp
= fd_info
[fd
].cp
;
7198 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7199 return STATUS_READ_ERROR
;
7201 cp
->status
= STATUS_READ_FAILED
;
7203 hEv
= pfn_WSACreateEvent ();
7204 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7205 if (rc
!= SOCKET_ERROR
)
7208 rc
= WaitForSingleObject (hEv
, 500);
7210 } while (rc
== WAIT_TIMEOUT
7211 && cp
->status
!= STATUS_READ_ERROR
7213 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7214 if (rc
== WAIT_OBJECT_0
)
7215 cp
->status
= STATUS_READ_SUCCEEDED
;
7217 pfn_WSACloseEvent (hEv
);
7223 sys_read (int fd
, char * buffer
, unsigned int count
)
7228 char * orig_buffer
= buffer
;
7236 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7238 child_process
*cp
= fd_info
[fd
].cp
;
7240 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7248 /* re-read CR carried over from last read */
7249 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7251 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7255 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7258 /* presence of a child_process structure means we are operating in
7259 non-blocking mode - otherwise we just call _read directly.
7260 Note that the child_process structure might be missing because
7261 reap_subprocess has been called; in this case the pipe is
7262 already broken, so calling _read on it is okay. */
7265 int current_status
= cp
->status
;
7267 switch (current_status
)
7269 case STATUS_READ_FAILED
:
7270 case STATUS_READ_ERROR
:
7271 /* report normal EOF if nothing in buffer */
7273 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7276 case STATUS_READ_READY
:
7277 case STATUS_READ_IN_PROGRESS
:
7278 DebPrint (("sys_read called when read is in progress\n"));
7279 errno
= EWOULDBLOCK
;
7282 case STATUS_READ_SUCCEEDED
:
7283 /* consume read-ahead char */
7284 *buffer
++ = cp
->chr
;
7287 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7288 ResetEvent (cp
->char_avail
);
7290 case STATUS_READ_ACKNOWLEDGED
:
7294 DebPrint (("sys_read: bad status %d\n", current_status
));
7299 if (fd_info
[fd
].flags
& FILE_PIPE
)
7301 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7302 to_read
= min (waiting
, (DWORD
) count
);
7305 nchars
+= _read (fd
, buffer
, to_read
);
7307 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7309 HANDLE hnd
= fd_info
[fd
].hnd
;
7310 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7316 /* Configure timeouts for non-blocking read. */
7317 if (!GetCommTimeouts (hnd
, &ct
))
7322 ct
.ReadIntervalTimeout
= MAXDWORD
;
7323 ct
.ReadTotalTimeoutMultiplier
= 0;
7324 ct
.ReadTotalTimeoutConstant
= 0;
7325 if (!SetCommTimeouts (hnd
, &ct
))
7331 if (!ResetEvent (ovl
->hEvent
))
7336 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
7338 if (GetLastError () != ERROR_IO_PENDING
)
7343 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7352 else /* FILE_SOCKET */
7354 if (winsock_lib
== NULL
) emacs_abort ();
7356 /* do the equivalent of a non-blocking read */
7357 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
7358 if (waiting
== 0 && nchars
== 0)
7360 errno
= EWOULDBLOCK
;
7366 /* always use binary mode for sockets */
7367 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
7368 if (res
== SOCKET_ERROR
)
7370 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
7371 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
7381 int nread
= _read (fd
, buffer
, count
);
7384 else if (nchars
== 0)
7389 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7390 /* Perform text mode translation if required. */
7391 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7393 nchars
= crlf_to_lf (nchars
, orig_buffer
);
7394 /* If buffer contains only CR, return that. To be absolutely
7395 sure we should attempt to read the next char, but in
7396 practice a CR to be followed by LF would not appear by
7397 itself in the buffer. */
7398 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
7400 fd_info
[fd
].flags
|= FILE_LAST_CR
;
7406 nchars
= _read (fd
, buffer
, count
);
7411 /* From w32xfns.c */
7412 extern HANDLE interrupt_handle
;
7414 /* For now, don't bother with a non-blocking mode */
7416 sys_write (int fd
, const void * buffer
, unsigned int count
)
7426 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7428 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
7434 /* Perform text mode translation if required. */
7435 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
7437 char * tmpbuf
= alloca (count
* 2);
7438 unsigned char * src
= (void *)buffer
;
7439 unsigned char * dst
= tmpbuf
;
7444 unsigned char *next
;
7445 /* copy next line or remaining bytes */
7446 next
= _memccpy (dst
, src
, '\n', nbytes
);
7449 /* copied one line ending with '\n' */
7450 int copied
= next
- dst
;
7453 /* insert '\r' before '\n' */
7460 /* copied remaining partial line -> now finished */
7467 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
7469 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
7470 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
7471 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
7474 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
7476 if (GetLastError () != ERROR_IO_PENDING
)
7481 if (detect_input_pending ())
7482 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
7485 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
7486 if (active
== WAIT_OBJECT_0
)
7487 { /* User pressed C-g, cancel write, then leave. Don't bother
7488 cleaning up as we may only get stuck in buggy drivers. */
7489 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
7494 if (active
== WAIT_OBJECT_0
+ 1
7495 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
7502 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
7504 unsigned long nblock
= 0;
7505 if (winsock_lib
== NULL
) emacs_abort ();
7507 /* TODO: implement select() properly so non-blocking I/O works. */
7508 /* For now, make sure the write blocks. */
7509 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7510 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7512 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
7514 /* Set the socket back to non-blocking if it was before,
7515 for other operations that support it. */
7516 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7519 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7522 if (nchars
== SOCKET_ERROR
)
7524 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
7525 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
7531 /* Some networked filesystems don't like too large writes, so
7532 break them into smaller chunks. See the Comments section of
7533 the MSDN documentation of WriteFile for details behind the
7534 choice of the value of CHUNK below. See also the thread
7535 http://thread.gmane.org/gmane.comp.version-control.git/145294
7536 in the git mailing list. */
7537 const unsigned char *p
= buffer
;
7538 const unsigned chunk
= 30 * 1024 * 1024;
7543 unsigned this_chunk
= count
< chunk
? count
: chunk
;
7544 int n
= _write (fd
, p
, this_chunk
);
7552 else if (n
< this_chunk
)
7563 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
7565 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
7567 /* Return information about network interface IFNAME, or about all
7568 interfaces (if IFNAME is nil). */
7570 network_interface_get_info (Lisp_Object ifname
)
7572 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
7573 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
7574 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
7575 Lisp_Object res
= Qnil
;
7577 if (retval
== ERROR_BUFFER_OVERFLOW
)
7579 ainfo
= xrealloc (ainfo
, ainfo_len
);
7580 retval
= get_adapters_info (ainfo
, &ainfo_len
);
7583 if (retval
== ERROR_SUCCESS
)
7585 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
7586 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
7588 struct sockaddr_in sa
;
7590 /* For the below, we need some winsock functions, so make sure
7591 the winsock DLL is loaded. If we cannot successfully load
7592 it, they will have no use of the information we provide,
7594 if (!winsock_lib
&& !init_winsock (1))
7597 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
7599 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
7601 /* Present Unix-compatible interface names, instead of the
7602 Windows names, which are really GUIDs not readable by
7604 static const char *ifmt
[] = {
7605 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
7620 switch (adapter
->Type
)
7622 case MIB_IF_TYPE_ETHERNET
:
7623 /* Windows before Vista reports wireless adapters as
7624 Ethernet. Work around by looking at the Description
7626 if (strstr (adapter
->Description
, "Wireless "))
7629 if_num
= wlan_count
++;
7633 ifmt_idx
= ETHERNET
;
7634 if_num
= eth_count
++;
7637 case MIB_IF_TYPE_TOKENRING
:
7638 ifmt_idx
= TOKENRING
;
7639 if_num
= tr_count
++;
7641 case MIB_IF_TYPE_FDDI
:
7643 if_num
= fddi_count
++;
7645 case MIB_IF_TYPE_PPP
:
7647 if_num
= ppp_count
++;
7649 case MIB_IF_TYPE_SLIP
:
7651 if_num
= sl_count
++;
7653 case IF_TYPE_IEEE80211
:
7655 if_num
= wlan_count
++;
7657 case MIB_IF_TYPE_LOOPBACK
:
7660 ifmt_idx
= LOOPBACK
;
7661 if_num
= lo_count
++;
7667 ifmt_idx
= OTHER_IF
;
7668 if_num
= ifx_count
++;
7671 if (ifmt_idx
== NONE
)
7673 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
7675 sa
.sin_family
= AF_INET
;
7676 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
7677 if (ip_addr
== INADDR_NONE
)
7679 /* Bogus address, skip this interface. */
7682 sa
.sin_addr
.s_addr
= ip_addr
;
7685 res
= Fcons (Fcons (build_string (namebuf
),
7686 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7687 sizeof (struct sockaddr
))),
7689 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
7691 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
7692 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
7693 Lisp_Object flags
= Qnil
;
7697 /* Flags. We guess most of them by type, since the
7698 Windows flags are different and hard to get by. */
7699 flags
= Fcons (intern ("up"), flags
);
7700 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
7702 flags
= Fcons (intern ("broadcast"), flags
);
7703 flags
= Fcons (intern ("multicast"), flags
);
7705 flags
= Fcons (intern ("running"), flags
);
7706 if (ifmt_idx
== PPP
)
7708 flags
= Fcons (intern ("pointopoint"), flags
);
7709 flags
= Fcons (intern ("noarp"), flags
);
7711 if (adapter
->HaveWins
)
7712 flags
= Fcons (intern ("WINS"), flags
);
7713 if (adapter
->DhcpEnabled
)
7714 flags
= Fcons (intern ("dynamic"), flags
);
7716 res
= Fcons (flags
, res
);
7718 /* Hardware address and its family. */
7719 for (n
= 0; n
< adapter
->AddressLength
; n
++)
7720 p
->u
.contents
[n
] = make_number ((int) adapter
->Address
[n
]);
7721 /* Windows does not support AF_LINK or AF_PACKET family
7722 of addresses. Use an arbitrary family number that is
7723 identical to what GNU/Linux returns. */
7724 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
7727 sa
.sin_family
= AF_INET
;
7728 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
7729 if (net_mask
!= INADDR_NONE
)
7731 sa
.sin_addr
.s_addr
= net_mask
;
7733 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7734 sizeof (struct sockaddr
)),
7738 res
= Fcons (Qnil
, res
);
7740 sa
.sin_family
= AF_INET
;
7741 if (ip_addr
!= INADDR_NONE
)
7743 /* Broadcast address is only reported by
7744 GetAdaptersAddresses, which is of limited
7745 availability. Generate it on our own. */
7746 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
7748 sa
.sin_addr
.s_addr
= bcast_addr
;
7750 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7751 sizeof (struct sockaddr
)),
7755 sa
.sin_addr
.s_addr
= ip_addr
;
7757 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7758 sizeof (struct sockaddr
)),
7762 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
7765 /* GetAdaptersInfo is documented to not report loopback
7766 interfaces, so we generate one out of thin air. */
7769 sa
.sin_family
= AF_INET
;
7773 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
7774 res
= Fcons (Fcons (build_string ("lo"),
7775 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7776 sizeof (struct sockaddr
))),
7779 else if (strcmp (SSDATA (ifname
), "lo") == 0)
7781 res
= Fcons (Fcons (intern ("running"),
7782 Fcons (intern ("loopback"),
7783 Fcons (intern ("up"), Qnil
))), Qnil
);
7784 /* 772 is what 3 different GNU/Linux systems report for
7785 the loopback interface. */
7786 res
= Fcons (Fcons (make_number (772),
7787 Fmake_vector (make_number (6),
7790 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
7791 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7792 sizeof (struct sockaddr
)),
7794 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
7795 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7796 sizeof (struct sockaddr
)),
7798 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
7799 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
7800 sizeof (struct sockaddr
)),
7813 network_interface_list (void)
7815 return network_interface_get_info (Qnil
);
7819 network_interface_info (Lisp_Object ifname
)
7821 return network_interface_get_info (ifname
);
7825 /* The Windows CRT functions are "optimized for speed", so they don't
7826 check for timezone and DST changes if they were last called less
7827 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
7828 all Emacs features that repeatedly call time functions (e.g.,
7829 display-time) are in real danger of missing timezone and DST
7830 changes. Calling tzset before each localtime call fixes that. */
7832 sys_localtime (const time_t *t
)
7835 return localtime (t
);
7840 /* Try loading LIBRARY_ID from the file(s) specified in
7841 Vdynamic_library_alist. If the library is loaded successfully,
7842 return the handle of the DLL, and record the filename in the
7843 property :loaded-from of LIBRARY_ID. If the library could not be
7844 found, or when it was already loaded (because the handle is not
7845 recorded anywhere, and so is lost after use), return NULL.
7847 We could also save the handle in :loaded-from, but currently
7848 there's no use case for it. */
7850 w32_delayed_load (Lisp_Object library_id
)
7852 HMODULE library_dll
= NULL
;
7854 CHECK_SYMBOL (library_id
);
7856 if (CONSP (Vdynamic_library_alist
)
7857 && NILP (Fassq (library_id
, Vlibrary_cache
)))
7859 Lisp_Object found
= Qnil
;
7860 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
7863 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
7865 CHECK_STRING_CAR (dlls
);
7866 if ((library_dll
= LoadLibrary (SDATA (XCAR (dlls
)))))
7868 char name
[MAX_PATH
];
7871 len
= GetModuleFileNameA (library_dll
, name
, sizeof (name
));
7872 found
= Fcons (XCAR (dlls
),
7874 /* Possibly truncated */
7875 ? make_specified_string (name
, -1, len
, 1)
7881 Fput (library_id
, QCloaded_from
, found
);
7889 check_windows_init_file (void)
7891 /* A common indication that Emacs is not installed properly is when
7892 it cannot find the Windows installation file. If this file does
7893 not exist in the expected place, tell the user. */
7895 if (!noninteractive
&& !inhibit_window_system
7896 /* Vload_path is not yet initialized when we are loading
7898 && NILP (Vpurify_flag
))
7900 Lisp_Object init_file
;
7903 init_file
= build_string ("term/w32-win");
7904 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
);
7907 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
7908 char *init_file_name
= SDATA (init_file
);
7909 char *load_path
= SDATA (load_path_print
);
7910 char *buffer
= alloca (1024
7911 + strlen (init_file_name
)
7912 + strlen (load_path
));
7915 "The Emacs Windows initialization file \"%s.el\" "
7916 "could not be found in your Emacs installation. "
7917 "Emacs checked the following directories for this file:\n"
7919 "When Emacs cannot find this file, it usually means that it "
7920 "was not installed properly, or its distribution file was "
7921 "not unpacked properly.\nSee the README.W32 file in the "
7922 "top-level Emacs directory for more information.",
7923 init_file_name
, load_path
);
7926 "Emacs Abort Dialog",
7927 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
7928 /* Use the low-level system abort. */
7939 term_ntproc (int ignored
)
7945 /* shutdown the socket interface if necessary */
7952 init_ntproc (int dumping
)
7954 sigset_t initial_mask
= 0;
7956 /* Initialize the socket interface now if available and requested by
7957 the user by defining PRELOAD_WINSOCK; otherwise loading will be
7958 delayed until open-network-stream is called (w32-has-winsock can
7959 also be used to dynamically load or reload winsock).
7961 Conveniently, init_environment is called before us, so
7962 PRELOAD_WINSOCK can be set in the registry. */
7964 /* Always initialize this correctly. */
7967 if (getenv ("PRELOAD_WINSOCK") != NULL
)
7968 init_winsock (TRUE
);
7970 /* Initial preparation for subprocess support: replace our standard
7971 handles with non-inheritable versions. */
7974 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
7975 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
7976 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
7978 parent
= GetCurrentProcess ();
7980 /* ignore errors when duplicating and closing; typically the
7981 handles will be invalid when running as a gui program. */
7982 DuplicateHandle (parent
,
7983 GetStdHandle (STD_INPUT_HANDLE
),
7988 DUPLICATE_SAME_ACCESS
);
7990 DuplicateHandle (parent
,
7991 GetStdHandle (STD_OUTPUT_HANDLE
),
7996 DUPLICATE_SAME_ACCESS
);
7998 DuplicateHandle (parent
,
7999 GetStdHandle (STD_ERROR_HANDLE
),
8004 DUPLICATE_SAME_ACCESS
);
8010 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8011 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8013 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8016 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8017 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8019 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8022 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8023 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8025 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8029 /* unfortunately, atexit depends on implementation of malloc */
8030 /* atexit (term_ntproc); */
8033 /* Make sure we start with all signals unblocked. */
8034 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8035 signal (SIGABRT
, term_ntproc
);
8039 /* determine which drives are fixed, for GetCachedVolumeInformation */
8041 /* GetDriveType must have trailing backslash. */
8042 char drive
[] = "A:\\";
8044 /* Loop over all possible drive letters */
8045 while (*drive
<= 'Z')
8047 /* Record if this drive letter refers to a fixed drive. */
8048 fixed_drives
[DRIVE_INDEX (*drive
)] =
8049 (GetDriveType (drive
) == DRIVE_FIXED
);
8054 /* Reset the volume info cache. */
8055 volume_cache
= NULL
;
8060 shutdown_handler ensures that buffers' autosave files are
8061 up to date when the user logs off, or the system shuts down.
8064 shutdown_handler (DWORD type
)
8066 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8067 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8068 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8069 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8071 /* Shut down cleanly, making sure autosave files are up to date. */
8072 shut_down_emacs (0, Qnil
);
8075 /* Allow other handlers to handle this signal. */
8080 globals_of_w32 is used to initialize those global variables that
8081 must always be initialized on startup even when the global variable
8082 initialized is non zero (see the function main in emacs.c).
8085 globals_of_w32 (void)
8087 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8089 get_process_times_fn
= (GetProcessTimes_Proc
)
8090 GetProcAddress (kernel32
, "GetProcessTimes");
8092 DEFSYM (QCloaded_from
, ":loaded-from");
8094 g_b_init_is_windows_9x
= 0;
8095 g_b_init_open_process_token
= 0;
8096 g_b_init_get_token_information
= 0;
8097 g_b_init_lookup_account_sid
= 0;
8098 g_b_init_get_sid_sub_authority
= 0;
8099 g_b_init_get_sid_sub_authority_count
= 0;
8100 g_b_init_get_security_info
= 0;
8101 g_b_init_get_file_security
= 0;
8102 g_b_init_get_security_descriptor_owner
= 0;
8103 g_b_init_get_security_descriptor_group
= 0;
8104 g_b_init_is_valid_sid
= 0;
8105 g_b_init_create_toolhelp32_snapshot
= 0;
8106 g_b_init_process32_first
= 0;
8107 g_b_init_process32_next
= 0;
8108 g_b_init_open_thread_token
= 0;
8109 g_b_init_impersonate_self
= 0;
8110 g_b_init_revert_to_self
= 0;
8111 g_b_init_get_process_memory_info
= 0;
8112 g_b_init_get_process_working_set_size
= 0;
8113 g_b_init_global_memory_status
= 0;
8114 g_b_init_global_memory_status_ex
= 0;
8115 g_b_init_equal_sid
= 0;
8116 g_b_init_copy_sid
= 0;
8117 g_b_init_get_length_sid
= 0;
8118 g_b_init_get_native_system_info
= 0;
8119 g_b_init_get_system_times
= 0;
8120 g_b_init_create_symbolic_link
= 0;
8121 g_b_init_get_security_descriptor_dacl
= 0;
8122 g_b_init_convert_sd_to_sddl
= 0;
8123 g_b_init_convert_sddl_to_sd
= 0;
8124 g_b_init_is_valid_security_descriptor
= 0;
8125 g_b_init_set_file_security
= 0;
8126 g_b_init_get_adapters_info
= 0;
8127 num_of_processors
= 0;
8128 /* The following sets a handler for shutdown notifications for
8129 console apps. This actually applies to Emacs in both console and
8130 GUI modes, since we had to fool windows into thinking emacs is a
8131 console application to get console mode to work. */
8132 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8134 /* "None" is the default group name on standalone workstations. */
8135 strcpy (dflt_group_name
, "None");
8137 /* Reset, in case it has some value inherited from dump time. */
8138 w32_stat_get_owner_group
= 0;
8140 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8141 (a.k.a. "wide") APIs to invoke functions that accept file
8143 if (is_windows_9x ())
8144 w32_unicode_filenames
= 0;
8146 w32_unicode_filenames
= 1;
8149 /* For make-serial-process */
8151 serial_open (Lisp_Object port_obj
)
8153 char *port
= SSDATA (port_obj
);
8158 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8159 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8160 if (hnd
== INVALID_HANDLE_VALUE
)
8161 error ("Could not open %s", port
);
8162 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8164 error ("Could not open %s", port
);
8168 error ("Could not create child process");
8170 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8171 fd_info
[ fd
].hnd
= hnd
;
8172 fd_info
[ fd
].flags
|=
8173 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8174 if (fd_info
[ fd
].cp
!= NULL
)
8176 error ("fd_info[fd = %d] is already in use", fd
);
8178 fd_info
[ fd
].cp
= cp
;
8179 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8180 if (cp
->ovl_read
.hEvent
== NULL
)
8181 error ("Could not create read event");
8182 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8183 if (cp
->ovl_write
.hEvent
== NULL
)
8184 error ("Could not create write event");
8189 /* For serial-process-configure */
8191 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8193 Lisp_Object childp2
= Qnil
;
8194 Lisp_Object tem
= Qnil
;
8198 char summary
[4] = "???"; /* This usually becomes "8N1". */
8200 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8201 error ("Not a serial process");
8202 hnd
= fd_info
[ p
->outfd
].hnd
;
8204 childp2
= Fcopy_sequence (p
->childp
);
8206 /* Initialize timeouts for blocking read and blocking write. */
8207 if (!GetCommTimeouts (hnd
, &ct
))
8208 error ("GetCommTimeouts() failed");
8209 ct
.ReadIntervalTimeout
= 0;
8210 ct
.ReadTotalTimeoutMultiplier
= 0;
8211 ct
.ReadTotalTimeoutConstant
= 0;
8212 ct
.WriteTotalTimeoutMultiplier
= 0;
8213 ct
.WriteTotalTimeoutConstant
= 0;
8214 if (!SetCommTimeouts (hnd
, &ct
))
8215 error ("SetCommTimeouts() failed");
8216 /* Read port attributes and prepare default configuration. */
8217 memset (&dcb
, 0, sizeof (dcb
));
8218 dcb
.DCBlength
= sizeof (DCB
);
8219 if (!GetCommState (hnd
, &dcb
))
8220 error ("GetCommState() failed");
8223 dcb
.fAbortOnError
= FALSE
;
8224 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8229 /* Configure speed. */
8230 if (!NILP (Fplist_member (contact
, QCspeed
)))
8231 tem
= Fplist_get (contact
, QCspeed
);
8233 tem
= Fplist_get (p
->childp
, QCspeed
);
8235 dcb
.BaudRate
= XINT (tem
);
8236 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8238 /* Configure bytesize. */
8239 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8240 tem
= Fplist_get (contact
, QCbytesize
);
8242 tem
= Fplist_get (p
->childp
, QCbytesize
);
8244 tem
= make_number (8);
8246 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8247 error (":bytesize must be nil (8), 7, or 8");
8248 dcb
.ByteSize
= XINT (tem
);
8249 summary
[0] = XINT (tem
) + '0';
8250 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8252 /* Configure parity. */
8253 if (!NILP (Fplist_member (contact
, QCparity
)))
8254 tem
= Fplist_get (contact
, QCparity
);
8256 tem
= Fplist_get (p
->childp
, QCparity
);
8257 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8258 error (":parity must be nil (no parity), `even', or `odd'");
8259 dcb
.fParity
= FALSE
;
8260 dcb
.Parity
= NOPARITY
;
8261 dcb
.fErrorChar
= FALSE
;
8266 else if (EQ (tem
, Qeven
))
8270 dcb
.Parity
= EVENPARITY
;
8271 dcb
.fErrorChar
= TRUE
;
8273 else if (EQ (tem
, Qodd
))
8277 dcb
.Parity
= ODDPARITY
;
8278 dcb
.fErrorChar
= TRUE
;
8280 childp2
= Fplist_put (childp2
, QCparity
, tem
);
8282 /* Configure stopbits. */
8283 if (!NILP (Fplist_member (contact
, QCstopbits
)))
8284 tem
= Fplist_get (contact
, QCstopbits
);
8286 tem
= Fplist_get (p
->childp
, QCstopbits
);
8288 tem
= make_number (1);
8290 if (XINT (tem
) != 1 && XINT (tem
) != 2)
8291 error (":stopbits must be nil (1 stopbit), 1, or 2");
8292 summary
[2] = XINT (tem
) + '0';
8293 if (XINT (tem
) == 1)
8294 dcb
.StopBits
= ONESTOPBIT
;
8295 else if (XINT (tem
) == 2)
8296 dcb
.StopBits
= TWOSTOPBITS
;
8297 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
8299 /* Configure flowcontrol. */
8300 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
8301 tem
= Fplist_get (contact
, QCflowcontrol
);
8303 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
8304 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
8305 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
8306 dcb
.fOutxCtsFlow
= FALSE
;
8307 dcb
.fOutxDsrFlow
= FALSE
;
8308 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
8309 dcb
.fDsrSensitivity
= FALSE
;
8310 dcb
.fTXContinueOnXoff
= FALSE
;
8313 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
8314 dcb
.XonChar
= 17; /* Control-Q */
8315 dcb
.XoffChar
= 19; /* Control-S */
8318 /* Already configured. */
8320 else if (EQ (tem
, Qhw
))
8322 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
8323 dcb
.fOutxCtsFlow
= TRUE
;
8325 else if (EQ (tem
, Qsw
))
8330 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
8332 /* Activate configuration. */
8333 if (!SetCommState (hnd
, &dcb
))
8334 error ("SetCommState() failed");
8336 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
8337 pset_childp (p
, childp2
);
8343 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
8347 struct timespec timeout
;
8348 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8349 int fd
= process
->infd
;
8351 n
= sys_read (fd
, (char*)buf
, sz
);
8358 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8359 if (err
== EWOULDBLOCK
)
8362 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
8368 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
8370 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
8371 int fd
= process
->outfd
;
8372 ssize_t n
= sys_write (fd
, buf
, sz
);
8374 /* 0 or more bytes written means everything went fine. */
8378 /* Negative bytes written means we got an error in errno.
8379 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
8380 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
8381 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
8385 #endif /* HAVE_GNUTLS */