1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2018 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or (at
10 your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #define DEFER_MS_W32_H
27 #include <mingw_time.h>
28 #include <stddef.h> /* for offsetof */
31 #include <float.h> /* for DBL_EPSILON */
38 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
40 #include <sys/utime.h>
43 /* Include (most) CRT headers *before* ms-w32.h. */
46 #include <string.h> /* for strerror, needed by sys_strerror */
47 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
73 char *sys_ctime (const time_t *);
74 int sys_chdir (const char *);
75 int sys_creat (const char *, int);
76 FILE *sys_fopen (const char *, const char *);
77 int sys_open (const char *, int, int);
78 int sys_rename (char const *, char const *);
79 int sys_rmdir (const char *);
81 int sys_dup2 (int, int);
82 int sys_read (int, char *, unsigned int);
83 int sys_write (int, const void *, unsigned int);
84 struct tm
*sys_localtime (const time_t *);
85 /* MinGW64 system headers include string.h too early, causing the
86 compiler to emit a warning about sys_strerror having no
88 char *sys_strerror (int);
91 extern void dynlib_reset_last_error (void);
95 #include "epaths.h" /* for PATH_EXEC */
101 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
102 use a different name to avoid compilation problems. */
103 typedef struct _MEMORY_STATUS_EX
{
106 DWORDLONG ullTotalPhys
;
107 DWORDLONG ullAvailPhys
;
108 DWORDLONG ullTotalPageFile
;
109 DWORDLONG ullAvailPageFile
;
110 DWORDLONG ullTotalVirtual
;
111 DWORDLONG ullAvailVirtual
;
112 DWORDLONG ullAvailExtendedVirtual
;
113 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
115 /* These are here so that GDB would know about these data types. This
116 allows attaching GDB to Emacs when a fatal exception is triggered
117 and Windows pops up the "application needs to be closed" dialog.
118 At that point, _gnu_exception_handler, the top-level exception
119 handler installed by the MinGW startup code, is somewhere on the
120 call-stack of the main thread, so going to that call frame and
121 looking at the argument to _gnu_exception_handler, which is a
122 PEXCEPTION_POINTERS pointer, can reveal the exception code
123 (excptr->ExceptionRecord->ExceptionCode) and the address where the
124 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
125 well as some additional information specific to the exception. */
126 PEXCEPTION_POINTERS excptr
;
127 PEXCEPTION_RECORD excprec
;
133 #include <tlhelp32.h>
138 #if _WIN32_WINNT < 0x0500
139 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
140 /* This either is not in psapi.h or guarded by higher value of
141 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
142 defines it in psapi.h */
143 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
145 DWORD PageFaultCount
;
146 SIZE_T PeakWorkingSetSize
;
147 SIZE_T WorkingSetSize
;
148 SIZE_T QuotaPeakPagedPoolUsage
;
149 SIZE_T QuotaPagedPoolUsage
;
150 SIZE_T QuotaPeakNonPagedPoolUsage
;
151 SIZE_T QuotaNonPagedPoolUsage
;
152 SIZE_T PagefileUsage
;
153 SIZE_T PeakPagefileUsage
;
155 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
159 #include <winioctl.h>
166 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
167 define them by hand if not already defined. */
168 #ifndef SDDL_REVISION_1
169 #define SDDL_REVISION_1 1
170 #endif /* SDDL_REVISION_1 */
172 #if defined(_MSC_VER) || defined(MINGW_W64)
173 /* MSVC and MinGW64 don't provide the definition of
174 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
175 which cannot be included because it triggers conflicts with other
176 Windows API headers. So we define it here by hand. */
178 typedef struct _REPARSE_DATA_BUFFER
{
180 USHORT ReparseDataLength
;
184 USHORT SubstituteNameOffset
;
185 USHORT SubstituteNameLength
;
186 USHORT PrintNameOffset
;
187 USHORT PrintNameLength
;
190 } SymbolicLinkReparseBuffer
;
192 USHORT SubstituteNameOffset
;
193 USHORT SubstituteNameLength
;
194 USHORT PrintNameOffset
;
195 USHORT PrintNameLength
;
197 } MountPointReparseBuffer
;
200 } GenericReparseBuffer
;
202 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
204 #ifndef FILE_DEVICE_FILE_SYSTEM
205 #define FILE_DEVICE_FILE_SYSTEM 9
207 #ifndef METHOD_BUFFERED
208 #define METHOD_BUFFERED 0
210 #ifndef FILE_ANY_ACCESS
211 #define FILE_ANY_ACCESS 0x00000000
214 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
216 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
217 #ifndef FSCTL_GET_REPARSE_POINT
218 #define FSCTL_GET_REPARSE_POINT \
219 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
223 /* TCP connection support. */
224 #include <sys/socket.h>
243 #include <iphlpapi.h> /* should be after winsock2.h */
245 #include <wincrypt.h>
247 #include <c-strcase.h>
248 #include <utimens.h> /* for fdutimens */
252 #include "w32common.h"
253 #include "w32select.h"
254 #include "systime.h" /* for current_timespec, struct timespec */
255 #include "dispextern.h" /* for xstrcasecmp */
256 #include "coding.h" /* for Vlocale_coding_system */
258 #include "careadlinkat.h"
259 #include "allocator.h"
261 /* For Lisp_Process, serial_configure and serial_open. */
265 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
266 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
268 static DWORD
get_rid (PSID
);
269 static int is_symlink (const char *);
270 static char * chase_symlinks (const char *);
271 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
272 static int restore_privilege (TOKEN_PRIVILEGES
*);
273 static BOOL WINAPI
revert_to_self (void);
275 static int sys_access (const char *, int);
276 extern void *e_malloc (size_t);
277 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
278 const struct timespec
*, const sigset_t
*);
279 extern int sys_dup (int);
282 /* Initialization states.
284 WARNING: If you add any more such variables for additional APIs,
285 you MUST add initialization for them to globals_of_w32
286 below. This is because these variables might get set
287 to non-NULL values during dumping, but the dumped Emacs
288 cannot reuse those values, because it could be run on a
289 different version of the OS, where API addresses are
291 static BOOL g_b_init_is_windows_9x
;
292 static BOOL g_b_init_open_process_token
;
293 static BOOL g_b_init_get_token_information
;
294 static BOOL g_b_init_lookup_account_sid
;
295 static BOOL g_b_init_get_sid_sub_authority
;
296 static BOOL g_b_init_get_sid_sub_authority_count
;
297 static BOOL g_b_init_get_security_info
;
298 static BOOL g_b_init_get_file_security_w
;
299 static BOOL g_b_init_get_file_security_a
;
300 static BOOL g_b_init_get_security_descriptor_owner
;
301 static BOOL g_b_init_get_security_descriptor_group
;
302 static BOOL g_b_init_is_valid_sid
;
303 static BOOL g_b_init_create_toolhelp32_snapshot
;
304 static BOOL g_b_init_process32_first
;
305 static BOOL g_b_init_process32_next
;
306 static BOOL g_b_init_open_thread_token
;
307 static BOOL g_b_init_impersonate_self
;
308 static BOOL g_b_init_revert_to_self
;
309 static BOOL g_b_init_get_process_memory_info
;
310 static BOOL g_b_init_get_process_working_set_size
;
311 static BOOL g_b_init_global_memory_status
;
312 static BOOL g_b_init_global_memory_status_ex
;
313 static BOOL g_b_init_get_length_sid
;
314 static BOOL g_b_init_equal_sid
;
315 static BOOL g_b_init_copy_sid
;
316 static BOOL g_b_init_get_native_system_info
;
317 static BOOL g_b_init_get_system_times
;
318 static BOOL g_b_init_create_symbolic_link_w
;
319 static BOOL g_b_init_create_symbolic_link_a
;
320 static BOOL g_b_init_get_security_descriptor_dacl
;
321 static BOOL g_b_init_convert_sd_to_sddl
;
322 static BOOL g_b_init_convert_sddl_to_sd
;
323 static BOOL g_b_init_is_valid_security_descriptor
;
324 static BOOL g_b_init_set_file_security_w
;
325 static BOOL g_b_init_set_file_security_a
;
326 static BOOL g_b_init_set_named_security_info_w
;
327 static BOOL g_b_init_set_named_security_info_a
;
328 static BOOL g_b_init_get_adapters_info
;
329 static BOOL g_b_init_reg_open_key_ex_w
;
330 static BOOL g_b_init_reg_query_value_ex_w
;
331 static BOOL g_b_init_expand_environment_strings_w
;
333 BOOL g_b_init_compare_string_w
;
334 BOOL g_b_init_debug_break_process
;
337 BEGIN: Wrapper functions around OpenProcessToken
338 and other functions in advapi32.dll that are only
339 supported in Windows NT / 2k / XP
341 /* ** Function pointer typedefs ** */
342 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
343 HANDLE ProcessHandle
,
345 PHANDLE TokenHandle
);
346 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
348 TOKEN_INFORMATION_CLASS TokenInformationClass
,
349 LPVOID TokenInformation
,
350 DWORD TokenInformationLength
,
351 PDWORD ReturnLength
);
352 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
353 HANDLE process_handle
,
354 LPFILETIME creation_time
,
355 LPFILETIME exit_time
,
356 LPFILETIME kernel_time
,
357 LPFILETIME user_time
);
359 GetProcessTimes_Proc get_process_times_fn
= NULL
;
362 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
364 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
366 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
367 LPCTSTR lpSystemName
,
372 LPDWORD cbDomainName
,
373 PSID_NAME_USE peUse
);
374 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
377 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
379 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
381 SE_OBJECT_TYPE ObjectType
,
382 SECURITY_INFORMATION SecurityInfo
,
387 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
388 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
390 SECURITY_INFORMATION RequestedInformation
,
391 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
393 LPDWORD lpnLengthNeeded
);
394 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
396 SECURITY_INFORMATION RequestedInformation
,
397 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
399 LPDWORD lpnLengthNeeded
);
400 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
402 SECURITY_INFORMATION SecurityInformation
,
403 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
404 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
406 SECURITY_INFORMATION SecurityInformation
,
407 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
408 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
409 LPCWSTR lpObjectName
,
410 SE_OBJECT_TYPE ObjectType
,
411 SECURITY_INFORMATION SecurityInformation
,
416 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
418 SE_OBJECT_TYPE ObjectType
,
419 SECURITY_INFORMATION SecurityInformation
,
424 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
425 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
427 LPBOOL lpbOwnerDefaulted
);
428 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
429 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
431 LPBOOL lpbGroupDefaulted
);
432 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
433 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
434 LPBOOL lpbDaclPresent
,
436 LPBOOL lpbDaclDefaulted
);
437 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
439 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
441 DWORD th32ProcessID
);
442 typedef BOOL (WINAPI
* Process32First_Proc
) (
444 LPPROCESSENTRY32 lppe
);
445 typedef BOOL (WINAPI
* Process32Next_Proc
) (
447 LPPROCESSENTRY32 lppe
);
448 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
452 PHANDLE TokenHandle
);
453 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
454 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
455 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
456 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
458 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
460 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
462 PSIZE_T lpMinimumWorkingSetSize
,
463 PSIZE_T lpMaximumWorkingSetSize
);
464 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
465 LPMEMORYSTATUS lpBuffer
);
466 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
467 LPMEMORY_STATUS_EX lpBuffer
);
468 typedef BOOL (WINAPI
* CopySid_Proc
) (
469 DWORD nDestinationSidLength
,
470 PSID pDestinationSid
,
472 typedef BOOL (WINAPI
* EqualSid_Proc
) (
475 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
477 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
478 LPSYSTEM_INFO lpSystemInfo
);
479 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
480 LPFILETIME lpIdleTime
,
481 LPFILETIME lpKernelTime
,
482 LPFILETIME lpUserTime
);
483 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
484 LPCWSTR lpSymlinkFileName
,
485 LPCWSTR lpTargetFileName
,
487 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
488 LPCSTR lpSymlinkFileName
,
489 LPCSTR lpTargetFileName
,
491 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
492 LPCTSTR StringSecurityDescriptor
,
493 DWORD StringSDRevision
,
494 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
495 PULONG SecurityDescriptorSize
);
496 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
497 PSECURITY_DESCRIPTOR SecurityDescriptor
,
498 DWORD RequestedStringSDRevision
,
499 SECURITY_INFORMATION SecurityInformation
,
500 LPTSTR
*StringSecurityDescriptor
,
501 PULONG StringSecurityDescriptorLen
);
502 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
503 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
504 PIP_ADAPTER_INFO pAdapterInfo
,
507 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
508 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
509 DWORD multiByteToWideCharFlags
;
510 typedef LONG (WINAPI
*RegOpenKeyExW_Proc
) (HKEY
,LPCWSTR
,DWORD
,REGSAM
,PHKEY
);
511 typedef LONG (WINAPI
*RegQueryValueExW_Proc
) (HKEY
,LPCWSTR
,LPDWORD
,LPDWORD
,LPBYTE
,LPDWORD
);
512 typedef DWORD (WINAPI
*ExpandEnvironmentStringsW_Proc
) (LPCWSTR
,LPWSTR
,DWORD
);
514 /* ** A utility function ** */
518 static BOOL s_b_ret
= 0;
519 OSVERSIONINFO os_ver
;
520 if (g_b_init_is_windows_9x
== 0)
522 g_b_init_is_windows_9x
= 1;
523 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
524 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
525 if (GetVersionEx (&os_ver
))
527 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
533 static Lisp_Object
ltime (ULONGLONG
);
535 /* Get total user and system times for get-internal-run-time.
536 Returns a list of integers if the times are provided by the OS
537 (NT derivatives), otherwise it returns the result of current-time. */
538 Lisp_Object
w32_get_internal_run_time (void);
541 w32_get_internal_run_time (void)
543 if (get_process_times_fn
)
545 FILETIME create
, exit
, kernel
, user
;
546 HANDLE proc
= GetCurrentProcess ();
547 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
549 LARGE_INTEGER user_int
, kernel_int
, total
;
550 user_int
.LowPart
= user
.dwLowDateTime
;
551 user_int
.HighPart
= user
.dwHighDateTime
;
552 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
553 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
554 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
555 return ltime (total
.QuadPart
);
559 return Fcurrent_time ();
562 /* ** The wrapper functions ** */
565 open_process_token (HANDLE ProcessHandle
,
569 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
570 HMODULE hm_advapi32
= NULL
;
571 if (is_windows_9x () == TRUE
)
575 if (g_b_init_open_process_token
== 0)
577 g_b_init_open_process_token
= 1;
578 hm_advapi32
= LoadLibrary ("Advapi32.dll");
579 s_pfn_Open_Process_Token
=
580 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
582 if (s_pfn_Open_Process_Token
== NULL
)
587 s_pfn_Open_Process_Token (
595 get_token_information (HANDLE TokenHandle
,
596 TOKEN_INFORMATION_CLASS TokenInformationClass
,
597 LPVOID TokenInformation
,
598 DWORD TokenInformationLength
,
601 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
602 HMODULE hm_advapi32
= NULL
;
603 if (is_windows_9x () == TRUE
)
607 if (g_b_init_get_token_information
== 0)
609 g_b_init_get_token_information
= 1;
610 hm_advapi32
= LoadLibrary ("Advapi32.dll");
611 s_pfn_Get_Token_Information
=
612 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
614 if (s_pfn_Get_Token_Information
== NULL
)
619 s_pfn_Get_Token_Information (
621 TokenInformationClass
,
623 TokenInformationLength
,
629 lookup_account_sid (LPCTSTR lpSystemName
,
634 LPDWORD cbDomainName
,
637 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
638 HMODULE hm_advapi32
= NULL
;
639 if (is_windows_9x () == TRUE
)
643 if (g_b_init_lookup_account_sid
== 0)
645 g_b_init_lookup_account_sid
= 1;
646 hm_advapi32
= LoadLibrary ("Advapi32.dll");
647 s_pfn_Lookup_Account_Sid
=
648 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
650 if (s_pfn_Lookup_Account_Sid
== NULL
)
655 s_pfn_Lookup_Account_Sid (
667 get_sid_sub_authority (PSID pSid
, DWORD n
)
669 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
670 static DWORD zero
= 0U;
671 HMODULE hm_advapi32
= NULL
;
672 if (is_windows_9x () == TRUE
)
676 if (g_b_init_get_sid_sub_authority
== 0)
678 g_b_init_get_sid_sub_authority
= 1;
679 hm_advapi32
= LoadLibrary ("Advapi32.dll");
680 s_pfn_Get_Sid_Sub_Authority
=
681 (GetSidSubAuthority_Proc
) GetProcAddress (
682 hm_advapi32
, "GetSidSubAuthority");
684 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
688 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
692 get_sid_sub_authority_count (PSID pSid
)
694 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
695 static UCHAR zero
= 0U;
696 HMODULE hm_advapi32
= NULL
;
697 if (is_windows_9x () == TRUE
)
701 if (g_b_init_get_sid_sub_authority_count
== 0)
703 g_b_init_get_sid_sub_authority_count
= 1;
704 hm_advapi32
= LoadLibrary ("Advapi32.dll");
705 s_pfn_Get_Sid_Sub_Authority_Count
=
706 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
707 hm_advapi32
, "GetSidSubAuthorityCount");
709 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
713 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
717 get_security_info (HANDLE handle
,
718 SE_OBJECT_TYPE ObjectType
,
719 SECURITY_INFORMATION SecurityInfo
,
724 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
726 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
727 HMODULE hm_advapi32
= NULL
;
728 if (is_windows_9x () == TRUE
)
732 if (g_b_init_get_security_info
== 0)
734 g_b_init_get_security_info
= 1;
735 hm_advapi32
= LoadLibrary ("Advapi32.dll");
736 s_pfn_Get_Security_Info
=
737 (GetSecurityInfo_Proc
) GetProcAddress (
738 hm_advapi32
, "GetSecurityInfo");
740 if (s_pfn_Get_Security_Info
== NULL
)
744 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
745 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
746 ppSecurityDescriptor
));
750 get_file_security (const char *lpFileName
,
751 SECURITY_INFORMATION RequestedInformation
,
752 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
754 LPDWORD lpnLengthNeeded
)
756 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
757 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
758 HMODULE hm_advapi32
= NULL
;
759 if (is_windows_9x () == TRUE
)
764 if (w32_unicode_filenames
)
766 wchar_t filename_w
[MAX_PATH
];
768 if (g_b_init_get_file_security_w
== 0)
770 g_b_init_get_file_security_w
= 1;
771 hm_advapi32
= LoadLibrary ("Advapi32.dll");
772 s_pfn_Get_File_SecurityW
=
773 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
776 if (s_pfn_Get_File_SecurityW
== NULL
)
781 filename_to_utf16 (lpFileName
, filename_w
);
782 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
783 pSecurityDescriptor
, nLength
,
788 char filename_a
[MAX_PATH
];
790 if (g_b_init_get_file_security_a
== 0)
792 g_b_init_get_file_security_a
= 1;
793 hm_advapi32
= LoadLibrary ("Advapi32.dll");
794 s_pfn_Get_File_SecurityA
=
795 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
798 if (s_pfn_Get_File_SecurityA
== NULL
)
803 filename_to_ansi (lpFileName
, filename_a
);
804 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
805 pSecurityDescriptor
, nLength
,
811 set_file_security (const char *lpFileName
,
812 SECURITY_INFORMATION SecurityInformation
,
813 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
815 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
816 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
817 HMODULE hm_advapi32
= NULL
;
818 if (is_windows_9x () == TRUE
)
823 if (w32_unicode_filenames
)
825 wchar_t filename_w
[MAX_PATH
];
827 if (g_b_init_set_file_security_w
== 0)
829 g_b_init_set_file_security_w
= 1;
830 hm_advapi32
= LoadLibrary ("Advapi32.dll");
831 s_pfn_Set_File_SecurityW
=
832 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
835 if (s_pfn_Set_File_SecurityW
== NULL
)
840 filename_to_utf16 (lpFileName
, filename_w
);
841 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
842 pSecurityDescriptor
));
846 char filename_a
[MAX_PATH
];
848 if (g_b_init_set_file_security_a
== 0)
850 g_b_init_set_file_security_a
= 1;
851 hm_advapi32
= LoadLibrary ("Advapi32.dll");
852 s_pfn_Set_File_SecurityA
=
853 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
856 if (s_pfn_Set_File_SecurityA
== NULL
)
861 filename_to_ansi (lpFileName
, filename_a
);
862 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
863 pSecurityDescriptor
));
868 set_named_security_info (LPCTSTR lpObjectName
,
869 SE_OBJECT_TYPE ObjectType
,
870 SECURITY_INFORMATION SecurityInformation
,
876 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
877 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
878 HMODULE hm_advapi32
= NULL
;
879 if (is_windows_9x () == TRUE
)
884 if (w32_unicode_filenames
)
886 wchar_t filename_w
[MAX_PATH
];
888 if (g_b_init_set_named_security_info_w
== 0)
890 g_b_init_set_named_security_info_w
= 1;
891 hm_advapi32
= LoadLibrary ("Advapi32.dll");
892 s_pfn_Set_Named_Security_InfoW
=
893 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
894 "SetNamedSecurityInfoW");
896 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
901 filename_to_utf16 (lpObjectName
, filename_w
);
902 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
903 SecurityInformation
, psidOwner
,
904 psidGroup
, pDacl
, pSacl
));
908 char filename_a
[MAX_PATH
];
910 if (g_b_init_set_named_security_info_a
== 0)
912 g_b_init_set_named_security_info_a
= 1;
913 hm_advapi32
= LoadLibrary ("Advapi32.dll");
914 s_pfn_Set_Named_Security_InfoA
=
915 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
916 "SetNamedSecurityInfoA");
918 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
923 filename_to_ansi (lpObjectName
, filename_a
);
924 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
925 SecurityInformation
, psidOwner
,
926 psidGroup
, pDacl
, pSacl
));
931 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
933 LPBOOL lpbOwnerDefaulted
)
935 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
936 HMODULE hm_advapi32
= NULL
;
937 if (is_windows_9x () == TRUE
)
942 if (g_b_init_get_security_descriptor_owner
== 0)
944 g_b_init_get_security_descriptor_owner
= 1;
945 hm_advapi32
= LoadLibrary ("Advapi32.dll");
946 s_pfn_Get_Security_Descriptor_Owner
=
947 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
948 hm_advapi32
, "GetSecurityDescriptorOwner");
950 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
955 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
960 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
962 LPBOOL lpbGroupDefaulted
)
964 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
965 HMODULE hm_advapi32
= NULL
;
966 if (is_windows_9x () == TRUE
)
971 if (g_b_init_get_security_descriptor_group
== 0)
973 g_b_init_get_security_descriptor_group
= 1;
974 hm_advapi32
= LoadLibrary ("Advapi32.dll");
975 s_pfn_Get_Security_Descriptor_Group
=
976 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
977 hm_advapi32
, "GetSecurityDescriptorGroup");
979 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
984 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
989 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
990 LPBOOL lpbDaclPresent
,
992 LPBOOL lpbDaclDefaulted
)
994 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
995 HMODULE hm_advapi32
= NULL
;
996 if (is_windows_9x () == TRUE
)
1001 if (g_b_init_get_security_descriptor_dacl
== 0)
1003 g_b_init_get_security_descriptor_dacl
= 1;
1004 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1005 s_pfn_Get_Security_Descriptor_Dacl
=
1006 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
1007 hm_advapi32
, "GetSecurityDescriptorDacl");
1009 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
1014 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
1015 lpbDaclPresent
, pDacl
,
1020 is_valid_sid (PSID sid
)
1022 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
1023 HMODULE hm_advapi32
= NULL
;
1024 if (is_windows_9x () == TRUE
)
1028 if (g_b_init_is_valid_sid
== 0)
1030 g_b_init_is_valid_sid
= 1;
1031 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1032 s_pfn_Is_Valid_Sid
=
1033 (IsValidSid_Proc
) GetProcAddress (
1034 hm_advapi32
, "IsValidSid");
1036 if (s_pfn_Is_Valid_Sid
== NULL
)
1040 return (s_pfn_Is_Valid_Sid (sid
));
1044 equal_sid (PSID sid1
, PSID sid2
)
1046 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1047 HMODULE hm_advapi32
= NULL
;
1048 if (is_windows_9x () == TRUE
)
1052 if (g_b_init_equal_sid
== 0)
1054 g_b_init_equal_sid
= 1;
1055 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1057 (EqualSid_Proc
) GetProcAddress (
1058 hm_advapi32
, "EqualSid");
1060 if (s_pfn_Equal_Sid
== NULL
)
1064 return (s_pfn_Equal_Sid (sid1
, sid2
));
1068 get_length_sid (PSID sid
)
1070 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1071 HMODULE hm_advapi32
= NULL
;
1072 if (is_windows_9x () == TRUE
)
1076 if (g_b_init_get_length_sid
== 0)
1078 g_b_init_get_length_sid
= 1;
1079 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1080 s_pfn_Get_Length_Sid
=
1081 (GetLengthSid_Proc
) GetProcAddress (
1082 hm_advapi32
, "GetLengthSid");
1084 if (s_pfn_Get_Length_Sid
== NULL
)
1088 return (s_pfn_Get_Length_Sid (sid
));
1092 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1094 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1095 HMODULE hm_advapi32
= NULL
;
1096 if (is_windows_9x () == TRUE
)
1100 if (g_b_init_copy_sid
== 0)
1102 g_b_init_copy_sid
= 1;
1103 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1105 (CopySid_Proc
) GetProcAddress (
1106 hm_advapi32
, "CopySid");
1108 if (s_pfn_Copy_Sid
== NULL
)
1112 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1116 END: Wrapper functions around OpenProcessToken
1117 and other functions in advapi32.dll that are only
1118 supported in Windows NT / 2k / XP
1122 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1124 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1125 if (is_windows_9x () != TRUE
)
1127 if (g_b_init_get_native_system_info
== 0)
1129 g_b_init_get_native_system_info
= 1;
1130 s_pfn_Get_Native_System_Info
=
1131 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1132 "GetNativeSystemInfo");
1134 if (s_pfn_Get_Native_System_Info
!= NULL
)
1135 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1138 lpSystemInfo
->dwNumberOfProcessors
= -1;
1142 get_system_times (LPFILETIME lpIdleTime
,
1143 LPFILETIME lpKernelTime
,
1144 LPFILETIME lpUserTime
)
1146 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1147 if (is_windows_9x () == TRUE
)
1151 if (g_b_init_get_system_times
== 0)
1153 g_b_init_get_system_times
= 1;
1154 s_pfn_Get_System_times
=
1155 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1158 if (s_pfn_Get_System_times
== NULL
)
1160 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1163 static BOOLEAN WINAPI
1164 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1165 LPCSTR lpTargetFileName
,
1168 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1169 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1172 if (is_windows_9x () == TRUE
)
1177 if (w32_unicode_filenames
)
1179 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1181 if (g_b_init_create_symbolic_link_w
== 0)
1183 g_b_init_create_symbolic_link_w
= 1;
1184 s_pfn_Create_Symbolic_LinkW
=
1185 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1186 "CreateSymbolicLinkW");
1188 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1194 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1195 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1196 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1197 /* If we were denied creation of the symlink, try again after
1198 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1201 TOKEN_PRIVILEGES priv_current
;
1203 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1206 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1207 restore_privilege (&priv_current
);
1214 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1216 if (g_b_init_create_symbolic_link_a
== 0)
1218 g_b_init_create_symbolic_link_a
= 1;
1219 s_pfn_Create_Symbolic_LinkA
=
1220 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1221 "CreateSymbolicLinkA");
1223 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1229 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1230 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1231 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1232 /* If we were denied creation of the symlink, try again after
1233 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1236 TOKEN_PRIVILEGES priv_current
;
1238 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1241 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1242 restore_privilege (&priv_current
);
1251 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1253 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1255 if (is_windows_9x () == TRUE
)
1261 if (g_b_init_is_valid_security_descriptor
== 0)
1263 g_b_init_is_valid_security_descriptor
= 1;
1264 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1265 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1266 "IsValidSecurityDescriptor");
1268 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1274 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1278 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1279 DWORD RequestedStringSDRevision
,
1280 SECURITY_INFORMATION SecurityInformation
,
1281 LPTSTR
*StringSecurityDescriptor
,
1282 PULONG StringSecurityDescriptorLen
)
1284 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1287 if (is_windows_9x () == TRUE
)
1293 if (g_b_init_convert_sd_to_sddl
== 0)
1295 g_b_init_convert_sd_to_sddl
= 1;
1297 s_pfn_Convert_SD_To_SDDL
=
1298 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1299 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1301 s_pfn_Convert_SD_To_SDDL
=
1302 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1303 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1306 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1312 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1313 RequestedStringSDRevision
,
1314 SecurityInformation
,
1315 StringSecurityDescriptor
,
1316 StringSecurityDescriptorLen
);
1322 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1323 DWORD StringSDRevision
,
1324 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1325 PULONG SecurityDescriptorSize
)
1327 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1330 if (is_windows_9x () == TRUE
)
1336 if (g_b_init_convert_sddl_to_sd
== 0)
1338 g_b_init_convert_sddl_to_sd
= 1;
1340 s_pfn_Convert_SDDL_To_SD
=
1341 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1342 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1344 s_pfn_Convert_SDDL_To_SD
=
1345 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1346 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1349 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1355 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1358 SecurityDescriptorSize
);
1364 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1366 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1367 HMODULE hm_iphlpapi
= NULL
;
1369 if (is_windows_9x () == TRUE
)
1370 return ERROR_NOT_SUPPORTED
;
1372 if (g_b_init_get_adapters_info
== 0)
1374 g_b_init_get_adapters_info
= 1;
1375 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1377 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1378 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1380 if (s_pfn_Get_Adapters_Info
== NULL
)
1381 return ERROR_NOT_SUPPORTED
;
1382 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1386 reg_open_key_ex_w (HKEY hkey
, LPCWSTR lpSubKey
, DWORD ulOptions
,
1387 REGSAM samDesired
, PHKEY phkResult
)
1389 static RegOpenKeyExW_Proc s_pfn_Reg_Open_Key_Ex_w
= NULL
;
1390 HMODULE hm_advapi32
= NULL
;
1392 if (is_windows_9x () == TRUE
)
1393 return ERROR_NOT_SUPPORTED
;
1395 if (g_b_init_reg_open_key_ex_w
== 0)
1397 g_b_init_reg_open_key_ex_w
= 1;
1398 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1400 s_pfn_Reg_Open_Key_Ex_w
= (RegOpenKeyExW_Proc
)
1401 GetProcAddress (hm_advapi32
, "RegOpenKeyExW");
1403 if (s_pfn_Reg_Open_Key_Ex_w
== NULL
)
1404 return ERROR_NOT_SUPPORTED
;
1405 return s_pfn_Reg_Open_Key_Ex_w (hkey
, lpSubKey
, ulOptions
,
1406 samDesired
, phkResult
);
1410 reg_query_value_ex_w (HKEY hkey
, LPCWSTR lpValueName
, LPDWORD lpReserved
,
1411 LPDWORD lpType
, LPBYTE lpData
, LPDWORD lpcbData
)
1413 static RegQueryValueExW_Proc s_pfn_Reg_Query_Value_Ex_w
= NULL
;
1414 HMODULE hm_advapi32
= NULL
;
1416 if (is_windows_9x () == TRUE
)
1417 return ERROR_NOT_SUPPORTED
;
1419 if (g_b_init_reg_query_value_ex_w
== 0)
1421 g_b_init_reg_query_value_ex_w
= 1;
1422 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1424 s_pfn_Reg_Query_Value_Ex_w
= (RegQueryValueExW_Proc
)
1425 GetProcAddress (hm_advapi32
, "RegQueryValueExW");
1427 if (s_pfn_Reg_Query_Value_Ex_w
== NULL
)
1428 return ERROR_NOT_SUPPORTED
;
1429 return s_pfn_Reg_Query_Value_Ex_w (hkey
, lpValueName
, lpReserved
,
1430 lpType
, lpData
, lpcbData
);
1434 expand_environment_strings_w (LPCWSTR lpSrc
, LPWSTR lpDst
, DWORD nSize
)
1436 static ExpandEnvironmentStringsW_Proc s_pfn_Expand_Environment_Strings_w
= NULL
;
1437 HMODULE hm_kernel32
= NULL
;
1439 if (is_windows_9x () == TRUE
)
1440 return ERROR_NOT_SUPPORTED
;
1442 if (g_b_init_expand_environment_strings_w
== 0)
1444 g_b_init_expand_environment_strings_w
= 1;
1445 hm_kernel32
= LoadLibrary ("Kernel32.dll");
1447 s_pfn_Expand_Environment_Strings_w
= (ExpandEnvironmentStringsW_Proc
)
1448 GetProcAddress (hm_kernel32
, "ExpandEnvironmentStringsW");
1450 if (s_pfn_Expand_Environment_Strings_w
== NULL
)
1455 return s_pfn_Expand_Environment_Strings_w (lpSrc
, lpDst
, nSize
);
1460 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1461 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1463 This is called from alloc.c:valid_pointer_p. */
1465 w32_valid_pointer_p (void *p
, int size
)
1468 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1472 unsigned char *buf
= alloca (size
);
1473 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1484 /* Here's an overview of how the Windows build supports file names
1485 that cannot be encoded by the current system codepage.
1487 From the POV of Lisp and layers of C code above the functions here,
1488 Emacs on Windows pretends that its file names are encoded in UTF-8;
1489 see encode_file and decode_file on coding.c. Any file name that is
1490 passed as a unibyte string to C functions defined here is assumed
1491 to be in UTF-8 encoding. Any file name returned by functions
1492 defined here must be in UTF-8 encoding, with only a few exceptions
1493 reserved for a couple of special cases. (Be sure to use
1494 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1495 as they can be much longer than MAX_PATH!)
1497 The UTF-8 encoded file names cannot be passed to system APIs, as
1498 Windows does not support that. Therefore, they are converted
1499 either to UTF-16 or to the ANSI codepage, depending on the value of
1500 w32-unicode-filenames, before calling any system APIs or CRT library
1501 functions. The default value of that variable is determined by the
1502 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1503 user can change that default (although I don't see why would she
1506 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1507 filename_from_utf16, and filename_from_ansi, are the workhorses of
1508 these conversions. They rely on Windows native APIs
1509 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1510 functions from coding.c here, because they allocate memory, which
1511 is a bad idea on the level of libc, which is what the functions
1512 here emulate. (If you worry about performance due to constant
1513 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1514 it was measured to take only a few microseconds on a not-so-fast
1515 machine, and second, that's exactly what the ANSI APIs we used
1516 before did anyway, because they are just thin wrappers around the
1519 The variables file-name-coding-system and default-file-name-coding-system
1520 still exist, but are actually used only when a file name needs to
1521 be converted to the ANSI codepage. This happens all the time when
1522 w32-unicode-filenames is nil, but can also happen from time to time
1523 when it is t. Otherwise, these variables have no effect on file-name
1524 encoding when w32-unicode-filenames is t; this is similar to
1525 selection-coding-system.
1527 This arrangement works very well, but it has a few gotchas and
1530 . Lisp code that encodes or decodes file names manually should
1531 normally use 'utf-8' as the coding-system on Windows,
1532 disregarding file-name-coding-system. This is a somewhat
1533 unpleasant consequence, but it cannot be avoided. Fortunately,
1534 very few Lisp packages need to do that.
1536 More generally, passing to library functions (e.g., fopen or
1537 opendir) file names already encoded in the ANSI codepage is
1538 explicitly *verboten*, as all those functions, as shadowed and
1539 emulated here, assume they will receive UTF-8 encoded file names.
1541 For the same reasons, no CRT function or Win32 API can be called
1542 directly in Emacs sources, without either converting the file
1543 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1544 some shadowing function defined here.
1546 . Environment variables stored in Vprocess_environment are encoded
1547 in the ANSI codepage, so if getenv/egetenv is used for a variable
1548 whose value is a file name or a list of directories, it needs to
1549 be converted to UTF-8, before it is used as argument to functions
1550 or decoded into a Lisp string.
1552 . File names passed to external libraries, like the image libraries
1553 and GnuTLS, need special handling. These libraries generally
1554 don't support UTF-16 or UTF-8 file names, so they must get file
1555 names encoded in the ANSI codepage. To facilitate using these
1556 libraries with file names that are not encodable in the ANSI
1557 codepage, use the function ansi_encode_filename, which will try
1558 to use the short 8+3 alias of a file name if that file name is
1559 not encodable in the ANSI codepage. See image.c and gnutls.c for
1560 examples of how this should be done.
1562 . Running subprocesses in non-ASCII directories and with non-ASCII
1563 file arguments is limited to the current codepage (even though
1564 Emacs is perfectly capable of finding an executable program file
1565 in a directory whose name cannot be encoded in the current
1566 codepage). This is because the command-line arguments are
1567 encoded _before_ they get to the w32-specific level, and the
1568 encoding is not known in advance (it doesn't have to be the
1569 current ANSI codepage), so w32proc.c functions cannot re-encode
1570 them in UTF-16. This should be fixed, but will also require
1571 changes in cmdproxy. The current limitation is not terribly bad
1572 anyway, since very few, if any, Windows console programs that are
1573 likely to be invoked by Emacs support UTF-16 encoded command
1576 . For similar reasons, server.el and emacsclient are also limited
1577 to the current ANSI codepage for now.
1579 . Emacs itself can only handle command-line arguments encoded in
1580 the current codepage.
1582 . Turning on w32-unicode-filename on Windows 9X (if it at all
1583 works) requires UNICOWS.DLL, which is thus a requirement even in
1584 non-GUI sessions, something that we previously avoided. */
1588 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1589 codepage defined by file-name-coding-system. */
1591 /* Current codepage for encoding file names. */
1592 static int file_name_codepage
;
1594 /* Initialize the codepage used for decoding file names. This is
1595 needed to undo the value recorded during dumping, which might not
1596 be correct when we run the dumped Emacs. */
1598 w32_init_file_name_codepage (void)
1600 file_name_codepage
= CP_ACP
;
1601 w32_ansi_code_page
= CP_ACP
;
1604 /* Produce a Windows ANSI codepage suitable for encoding file names.
1605 Return the information about that codepage in CP_INFO. */
1607 codepage_for_filenames (CPINFO
*cp_info
)
1609 /* A simple cache to avoid calling GetCPInfo every time we need to
1610 encode/decode a file name. The file-name encoding is not
1611 supposed to be changed too frequently, if ever. */
1612 static Lisp_Object last_file_name_encoding
;
1614 Lisp_Object current_encoding
;
1616 current_encoding
= Vfile_name_coding_system
;
1617 if (NILP (current_encoding
))
1618 current_encoding
= Vdefault_file_name_coding_system
;
1620 if (!EQ (last_file_name_encoding
, current_encoding
)
1621 || NILP (last_file_name_encoding
))
1623 /* Default to the current ANSI codepage. */
1624 file_name_codepage
= w32_ansi_code_page
;
1626 if (!NILP (current_encoding
))
1628 char *cpname
= SSDATA (SYMBOL_NAME (current_encoding
));
1629 char *cp
= NULL
, *end
;
1632 if (strncmp (cpname
, "cp", 2) == 0)
1634 else if (strncmp (cpname
, "windows-", 8) == 0)
1640 cpnum
= strtol (cp
, &end
, 10);
1641 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1642 file_name_codepage
= cpnum
;
1646 if (!file_name_codepage
)
1647 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1649 if (!GetCPInfo (file_name_codepage
, &cp
))
1651 file_name_codepage
= CP_ACP
;
1652 if (!GetCPInfo (file_name_codepage
, &cp
))
1656 /* Cache the new value. */
1657 last_file_name_encoding
= current_encoding
;
1662 return file_name_codepage
;
1666 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1668 int result
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, fn_in
,
1669 -1, fn_out
, MAX_PATH
);
1673 DWORD err
= GetLastError ();
1677 case ERROR_INVALID_FLAGS
:
1678 case ERROR_INVALID_PARAMETER
:
1681 case ERROR_INSUFFICIENT_BUFFER
:
1682 case ERROR_NO_UNICODE_TRANSLATION
:
1693 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1695 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1696 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1700 DWORD err
= GetLastError ();
1704 case ERROR_INVALID_FLAGS
:
1705 case ERROR_INVALID_PARAMETER
:
1708 case ERROR_INSUFFICIENT_BUFFER
:
1709 case ERROR_NO_UNICODE_TRANSLATION
:
1720 filename_to_ansi (const char *fn_in
, char *fn_out
)
1722 wchar_t fn_utf16
[MAX_PATH
];
1724 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1727 int codepage
= codepage_for_filenames (NULL
);
1729 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1730 fn_out
, MAX_PATH
, NULL
, NULL
);
1733 DWORD err
= GetLastError ();
1737 case ERROR_INVALID_FLAGS
:
1738 case ERROR_INVALID_PARAMETER
:
1741 case ERROR_INSUFFICIENT_BUFFER
:
1742 case ERROR_NO_UNICODE_TRANSLATION
:
1755 filename_from_ansi (const char *fn_in
, char *fn_out
)
1757 wchar_t fn_utf16
[MAX_PATH
];
1758 int codepage
= codepage_for_filenames (NULL
);
1759 int result
= pMultiByteToWideChar (codepage
, multiByteToWideCharFlags
, fn_in
,
1760 -1, fn_utf16
, MAX_PATH
);
1764 DWORD err
= GetLastError ();
1768 case ERROR_INVALID_FLAGS
:
1769 case ERROR_INVALID_PARAMETER
:
1772 case ERROR_INSUFFICIENT_BUFFER
:
1773 case ERROR_NO_UNICODE_TRANSLATION
:
1780 return filename_from_utf16 (fn_utf16
, fn_out
);
1785 /* The directory where we started, in UTF-8. */
1786 static char startup_dir
[MAX_UTF8_PATH
];
1788 /* Get the current working directory. */
1790 getcwd (char *dir
, int dirsize
)
1797 if (dirsize
<= strlen (startup_dir
))
1803 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1807 /* Emacs doesn't actually change directory itself, it stays in the
1808 same directory where it was started. */
1809 strcpy (dir
, startup_dir
);
1814 /* Emulate getloadavg. */
1816 struct load_sample
{
1823 /* Number of processors on this machine. */
1824 static unsigned num_of_processors
;
1826 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1827 static struct load_sample samples
[16*60];
1828 static int first_idx
= -1, last_idx
= -1;
1829 static int max_idx
= ARRAYELTS (samples
);
1834 int next_idx
= from
+ 1;
1836 if (next_idx
>= max_idx
)
1845 int prev_idx
= from
- 1;
1848 prev_idx
= max_idx
- 1;
1854 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1856 SYSTEM_INFO sysinfo
;
1857 FILETIME ft_idle
, ft_user
, ft_kernel
;
1859 /* Initialize the number of processors on this machine. */
1860 if (num_of_processors
<= 0)
1862 get_native_system_info (&sysinfo
);
1863 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1864 if (num_of_processors
<= 0)
1866 GetSystemInfo (&sysinfo
);
1867 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1869 if (num_of_processors
<= 0)
1870 num_of_processors
= 1;
1873 /* TODO: Take into account threads that are ready to run, by
1874 sampling the "\System\Processor Queue Length" performance
1875 counter. The code below accounts only for threads that are
1876 actually running. */
1878 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1880 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1882 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1883 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1884 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1885 *idle
= uidle
.QuadPart
;
1886 *kernel
= ukernel
.QuadPart
;
1887 *user
= uuser
.QuadPart
;
1897 /* Produce the load average for a given time interval, using the
1898 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1899 1-minute, 5-minute, or 15-minute average, respectively. */
1903 double retval
= -1.0;
1906 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1907 time_t now
= samples
[last_idx
].sample_time
;
1909 if (first_idx
!= last_idx
)
1911 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1913 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1914 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1917 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1918 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1919 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1921 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1924 if (idx
== first_idx
)
1933 getloadavg (double loadavg
[], int nelem
)
1936 ULONGLONG idle
, kernel
, user
;
1937 time_t now
= time (NULL
);
1939 /* If system time jumped back for some reason, delete all samples
1940 whose time is later than the current wall-clock time. This
1941 prevents load average figures from becoming frozen for prolonged
1942 periods of time, when system time is reset backwards. */
1945 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1947 if (last_idx
== first_idx
)
1949 first_idx
= last_idx
= -1;
1952 last_idx
= buf_prev (last_idx
);
1956 /* Store another sample. We ignore samples that are less than 1 sec
1959 || (difftime (now
, samples
[last_idx
].sample_time
)
1960 >= 1.0 - 2*DBL_EPSILON
*now
))
1962 sample_system_load (&idle
, &kernel
, &user
);
1963 last_idx
= buf_next (last_idx
);
1964 samples
[last_idx
].sample_time
= now
;
1965 samples
[last_idx
].idle
= idle
;
1966 samples
[last_idx
].kernel
= kernel
;
1967 samples
[last_idx
].user
= user
;
1968 /* If the buffer has more that 15 min worth of samples, discard
1970 if (first_idx
== -1)
1971 first_idx
= last_idx
;
1972 while (first_idx
!= last_idx
1973 && (difftime (now
, samples
[first_idx
].sample_time
)
1974 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1975 first_idx
= buf_next (first_idx
);
1978 for (elem
= 0; elem
< nelem
; elem
++)
1980 double avg
= getavg (elem
);
1984 loadavg
[elem
] = avg
;
1990 /* Emulate getpwuid, getpwnam and others. */
1992 #define PASSWD_FIELD_SIZE 256
1994 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1995 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1996 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1997 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1998 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
2000 static struct passwd dflt_passwd
=
2012 static char dflt_group_name
[GNLEN
+1];
2014 static struct group dflt_group
=
2016 /* When group information is not available, we return this as the
2017 group for all files. */
2025 return dflt_passwd
.pw_uid
;
2031 /* I could imagine arguing for checking to see whether the user is
2032 in the Administrators group and returning a UID of 0 for that
2033 case, but I don't know how wise that would be in the long run. */
2040 return dflt_passwd
.pw_gid
;
2050 getpwuid (unsigned uid
)
2052 if (uid
== dflt_passwd
.pw_uid
)
2053 return &dflt_passwd
;
2058 getgrgid (gid_t gid
)
2064 getpwnam (char *name
)
2068 pw
= getpwuid (getuid ());
2072 if (xstrcasecmp (name
, pw
->pw_name
))
2079 init_user_info (void)
2081 /* Find the user's real name by opening the process token and
2082 looking up the name associated with the user-sid in that token.
2084 Use the relative portion of the identifier authority value from
2085 the user-sid as the user id value (same for group id using the
2086 primary group sid from the process token). */
2088 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
2089 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
2090 DWORD glength
= sizeof (gname
);
2091 HANDLE token
= NULL
;
2092 SID_NAME_USE user_type
;
2093 unsigned char *buf
= NULL
;
2095 TOKEN_USER user_token
;
2096 TOKEN_PRIMARY_GROUP group_token
;
2099 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
2102 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
2103 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2105 buf
= xmalloc (blen
);
2106 result
= get_token_information (token
, TokenUser
,
2107 (LPVOID
)buf
, blen
, &needed
);
2110 memcpy (&user_token
, buf
, sizeof (user_token
));
2111 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
2113 domain
, &dlength
, &user_type
);
2121 strcpy (dflt_passwd
.pw_name
, uname
);
2122 /* Determine a reasonable uid value. */
2123 if (xstrcasecmp ("administrator", uname
) == 0)
2125 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2126 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2130 /* Use the last sub-authority value of the RID, the relative
2131 portion of the SID, as user/group ID. */
2132 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2134 /* Get group id and name. */
2135 result
= get_token_information (token
, TokenPrimaryGroup
,
2136 (LPVOID
)buf
, blen
, &needed
);
2137 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2139 buf
= xrealloc (buf
, blen
= needed
);
2140 result
= get_token_information (token
, TokenPrimaryGroup
,
2141 (LPVOID
)buf
, blen
, &needed
);
2145 memcpy (&group_token
, buf
, sizeof (group_token
));
2146 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2147 dlength
= sizeof (domain
);
2148 /* If we can get at the real Primary Group name, use that.
2149 Otherwise, the default group name was already set to
2150 "None" in globals_of_w32. */
2151 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2152 gname
, &glength
, NULL
, &dlength
,
2154 strcpy (dflt_group_name
, gname
);
2157 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2160 /* If security calls are not supported (presumably because we
2161 are running under Windows 9X), fallback to this: */
2162 else if (GetUserName (uname
, &ulength
))
2164 strcpy (dflt_passwd
.pw_name
, uname
);
2165 if (xstrcasecmp ("administrator", uname
) == 0)
2166 dflt_passwd
.pw_uid
= 0;
2168 dflt_passwd
.pw_uid
= 123;
2169 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2173 strcpy (dflt_passwd
.pw_name
, "unknown");
2174 dflt_passwd
.pw_uid
= 123;
2175 dflt_passwd
.pw_gid
= 123;
2177 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2179 /* Set dir and shell from environment variables. */
2180 if (w32_unicode_filenames
)
2182 wchar_t *home
= _wgetenv (L
"HOME");
2183 wchar_t *shell
= _wgetenv (L
"SHELL");
2185 /* Ensure HOME and SHELL are defined. */
2190 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2191 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2195 char *home
= getenv ("HOME");
2196 char *shell
= getenv ("SHELL");
2202 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2203 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2208 CloseHandle (token
);
2211 static HCRYPTPROV w32_crypto_hprov
;
2213 w32_init_crypt_random (void)
2215 if (!CryptAcquireContext (&w32_crypto_hprov
, NULL
, NULL
, PROV_RSA_FULL
,
2216 CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
2218 DebPrint (("CryptAcquireContext failed with error %x\n",
2220 w32_crypto_hprov
= 0;
2227 w32_init_random (void *buf
, ptrdiff_t buflen
)
2229 if (!w32_crypto_hprov
)
2230 w32_init_crypt_random ();
2231 if (w32_crypto_hprov
)
2233 if (CryptGenRandom (w32_crypto_hprov
, buflen
, (BYTE
*)buf
))
2239 /* MS-Windows 'rand' produces separate identical series for each
2240 thread, so we replace it with our version. */
2242 /* Algorithm AS183: An Efficient and Portable Pseudo-random Number
2243 Generator, by B.A. Wichmann, I.D. Hill. AS, v31, No. 2 (1982). */
2244 static int ix
= 3172, iy
= 9814, iz
= 20125;
2245 #define RAND_MAX_X 30269
2246 #define RAND_MAX_Y 30307
2247 #define RAND_MAX_Z 30323
2252 ix
= (171 * ix
) % RAND_MAX_X
;
2253 iy
= (172 * iy
) % RAND_MAX_Y
;
2254 iz
= (170 * iz
) % RAND_MAX_Z
;
2256 return (ix
+ iy
+ iz
) & 0x7fff;
2262 /* rand_as183 () gives us 15 random bits...hack together 30 bits. */
2263 return ((rand_as183 () << 15) | rand_as183 ());
2270 ix
= rand () % RAND_MAX_X
;
2271 iy
= rand () % RAND_MAX_Y
;
2272 iz
= rand () % RAND_MAX_Z
;
2275 /* Return the maximum length in bytes of a multibyte character
2276 sequence encoded in the current ANSI codepage. This is required to
2277 correctly walk the encoded file names one character at a time. */
2279 max_filename_mbslen (void)
2283 codepage_for_filenames (&cp_info
);
2284 return cp_info
.MaxCharSize
;
2287 /* Normalize filename by converting in-place all of its path
2288 separators to the separator specified by PATH_SEP. */
2291 normalize_filename (register char *fp
, char path_sep
)
2295 /* Always lower-case drive letters a-z, even if the filesystem
2296 preserves case in filenames.
2297 This is so filenames can be compared by string comparison
2298 functions that are case-sensitive. Even case-preserving filesystems
2299 do not distinguish case in drive letters. */
2302 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2310 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2316 /* Destructively turn backslashes into slashes. */
2318 dostounix_filename (register char *p
)
2320 normalize_filename (p
, '/');
2323 /* Destructively turn slashes into backslashes. */
2325 unixtodos_filename (register char *p
)
2327 normalize_filename (p
, '\\');
2330 /* Remove all CR's that are followed by a LF.
2331 (From msdos.c...probably should figure out a way to share it,
2332 although this code isn't going to ever change.) */
2334 crlf_to_lf (register int n
, register char *buf
)
2336 unsigned char *np
= (unsigned char *)buf
;
2337 unsigned char *startp
= np
;
2338 char *endp
= buf
+ n
;
2342 while (buf
< endp
- 1)
2346 if (*(++buf
) != 0x0a)
2357 /* Parse the root part of file name, if present. Return length and
2358 optionally store pointer to char after root. */
2360 parse_root (const char * name
, const char ** pPath
)
2362 const char * start
= name
;
2367 /* find the root name of the volume if given */
2368 if (isalpha (name
[0]) && name
[1] == ':')
2370 /* skip past drive specifier */
2372 if (IS_DIRECTORY_SEP (name
[0]))
2375 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2382 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2387 if (IS_DIRECTORY_SEP (name
[0]))
2394 return name
- start
;
2397 /* Get long base name for name; name is assumed to be absolute. */
2399 get_long_basename (char * name
, char * buf
, int size
)
2401 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2402 char fname_utf8
[MAX_UTF8_PATH
];
2406 /* Must be valid filename, no wild cards or other invalid characters. */
2407 if (strpbrk (name
, "*?|<>\""))
2410 if (w32_unicode_filenames
)
2412 wchar_t fname_utf16
[MAX_PATH
];
2413 WIN32_FIND_DATAW find_data_wide
;
2415 filename_to_utf16 (name
, fname_utf16
);
2416 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2417 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2418 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2422 char fname_ansi
[MAX_PATH
];
2423 WIN32_FIND_DATAA find_data_ansi
;
2425 filename_to_ansi (name
, fname_ansi
);
2426 /* If the ANSI name includes ? characters, it is not encodable
2427 in the ANSI codepage. In that case, we deliver the question
2428 marks to the caller; calling FindFirstFileA in this case
2429 could return some unrelated file name in the same
2431 if (_mbspbrk (fname_ansi
, "?"))
2433 /* Find the basename of fname_ansi. */
2434 char *p
= strrchr (fname_ansi
, '\\');
2440 cstatus
= filename_from_ansi (p
, fname_utf8
);
2444 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2445 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2446 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2450 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2451 memcpy (buf
, fname_utf8
, len
+ 1);
2455 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2456 FindClose (dir_handle
);
2461 /* Get long name for file, if possible (assumed to be absolute). */
2463 w32_get_long_filename (const char * name
, char * buf
, int size
)
2468 char full
[ MAX_UTF8_PATH
];
2471 len
= strlen (name
);
2472 if (len
>= MAX_UTF8_PATH
)
2475 /* Use local copy for destructive modification. */
2476 memcpy (full
, name
, len
+1);
2477 unixtodos_filename (full
);
2479 /* Copy root part verbatim. */
2480 len
= parse_root (full
, (const char **)&p
);
2481 memcpy (o
, full
, len
);
2486 while (p
!= NULL
&& *p
)
2489 p
= strchr (q
, '\\');
2491 len
= get_long_basename (full
, o
, size
);
2514 w32_get_short_filename (const char * name
, char * buf
, int size
)
2516 if (w32_unicode_filenames
)
2518 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2519 unsigned int retval
;
2521 filename_to_utf16 (name
, name_utf16
);
2522 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2523 if (retval
&& retval
< size
)
2524 filename_from_utf16 (short_name
, buf
);
2529 char name_ansi
[MAX_PATH
];
2531 filename_to_ansi (name
, name_ansi
);
2532 return GetShortPathNameA (name_ansi
, buf
, size
);
2536 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2537 MS-Windows ANSI codepage. If FILENAME includes characters not
2538 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2539 if it exists. This is needed because the w32 build wants to
2540 support file names outside of the system locale, but image
2541 libraries typically don't support wide (a.k.a. "Unicode") APIs
2542 required for that. */
2545 ansi_encode_filename (Lisp_Object filename
)
2547 Lisp_Object encoded_filename
;
2548 char fname
[MAX_PATH
];
2550 filename_to_ansi (SSDATA (filename
), fname
);
2551 if (_mbspbrk (fname
, "?"))
2553 char shortname
[MAX_PATH
];
2555 if (w32_get_short_filename (SSDATA (filename
), shortname
, MAX_PATH
))
2557 dostounix_filename (shortname
);
2558 encoded_filename
= build_string (shortname
);
2561 encoded_filename
= build_unibyte_string (fname
);
2564 encoded_filename
= build_unibyte_string (fname
);
2565 return encoded_filename
;
2569 is_unc_volume (const char *filename
)
2571 const char *ptr
= filename
;
2573 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2576 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2582 /* Emulate the Posix unsetenv. */
2584 unsetenv (const char *name
)
2589 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2594 name_len
= strlen (name
);
2595 /* MS docs says an environment variable cannot be longer than 32K. */
2596 if (name_len
> 32767)
2601 /* It is safe to use 'alloca' with 32K size, since the stack is at
2602 least 2MB, and we set it to 8MB in the link command line. */
2603 var
= alloca (name_len
+ 2);
2604 strncpy (var
, name
, name_len
);
2605 var
[name_len
++] = '=';
2606 var
[name_len
] = '\0';
2607 return _putenv (var
);
2610 /* MS _putenv doesn't support removing a variable when the argument
2611 does not include the '=' character, so we fix that here. */
2613 sys_putenv (char *str
)
2615 const char *const name_end
= strchr (str
, '=');
2617 if (name_end
== NULL
)
2619 /* Remove the variable from the environment. */
2620 return unsetenv (str
);
2623 if (strncmp (str
, "TZ=<", 4) == 0)
2625 /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
2626 abbreviation syntax. Convert to POSIX.1-1988 syntax if possible,
2627 and to the undocumented placeholder "ZZZ" otherwise. */
2628 bool supported_abbr
= true;
2629 for (char *p
= str
+ 4; *p
; p
++)
2631 if (('0' <= *p
&& *p
<= '9') || *p
== '-' || *p
== '+')
2632 supported_abbr
= false;
2638 abbrlen
= p
- (str
+ 4);
2639 memmove (str
+ 3, str
+ 4, abbrlen
);
2644 memset (str
+ 3, 'Z', abbrlen
);
2646 memmove (str
+ 3 + abbrlen
, p
+ 1, strlen (p
));
2652 return _putenv (str
);
2655 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2658 w32_get_resource (const char *key
, LPDWORD lpdwtype
)
2661 HKEY hrootkey
= NULL
;
2664 /* Check both the current user and the local machine to see if
2665 we have any resources. */
2667 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2671 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2672 && (lpvalue
= xmalloc (cbData
)) != NULL
2673 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2675 RegCloseKey (hrootkey
);
2681 RegCloseKey (hrootkey
);
2684 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2688 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2689 && (lpvalue
= xmalloc (cbData
)) != NULL
2690 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2692 RegCloseKey (hrootkey
);
2698 RegCloseKey (hrootkey
);
2704 /* The argv[] array holds ANSI-encoded strings, and so this function
2705 works with ANS_encoded strings. */
2707 init_environment (char ** argv
)
2709 static const char * const tempdirs
[] = {
2710 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2715 const int imax
= ARRAYELTS (tempdirs
);
2717 /* Implementation note: This function explicitly works with ANSI
2718 file names, not with UTF-8 encoded file names. This is because
2719 this function pushes variables into the Emacs's environment, and
2720 the environment variables are always assumed to be in the
2721 locale-specific encoding. Do NOT call any functions that accept
2722 UTF-8 file names from this function! */
2724 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2725 temporary files and assume "/tmp" if $TMPDIR is unset, which
2726 will break on DOS/Windows. Refuse to work if we cannot find
2727 a directory, not even "c:/", usable for that purpose. */
2728 for (i
= 0; i
< imax
; i
++)
2730 const char *tmp
= tempdirs
[i
];
2733 tmp
= getenv (tmp
+ 1);
2734 /* Note that `access' can lie to us if the directory resides on a
2735 read-only filesystem, like CD-ROM or a write-protected floppy.
2736 The only way to be really sure is to actually create a file and
2737 see if it succeeds. But I think that's too much to ask. */
2739 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2740 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2742 char * var
= alloca (strlen (tmp
) + 8);
2743 sprintf (var
, "TMPDIR=%s", tmp
);
2744 _putenv (strdup (var
));
2751 Fcons (build_string ("no usable temporary directories found!!"),
2753 "While setting TMPDIR: ");
2755 /* Check for environment variables and use registry settings if they
2756 don't exist. Fallback on default values where applicable. */
2761 char locale_name
[32];
2762 char default_home
[MAX_PATH
];
2765 static const struct env_entry
2768 const char * def_value
;
2771 /* If the default value is NULL, we will use the value from the
2772 outside environment or the Registry, but will not push the
2773 variable into the Emacs environment if it is defined neither
2774 in the Registry nor in the outside environment. */
2776 {"PRELOAD_WINSOCK", NULL
},
2777 {"emacs_dir", "C:/emacs"},
2778 {"EMACSLOADPATH", NULL
},
2779 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2780 {"EMACSDATA", NULL
},
2781 {"EMACSPATH", NULL
},
2788 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2790 /* We need to copy dflt_envvars[] and work on the copy because we
2791 don't want the dumped Emacs to inherit the values of
2792 environment variables we saw during dumping (which could be on
2793 a different system). The defaults above must be left intact. */
2794 struct env_entry env_vars
[N_ENV_VARS
];
2796 for (i
= 0; i
< N_ENV_VARS
; i
++)
2797 env_vars
[i
] = dflt_envvars
[i
];
2799 /* For backwards compatibility, check if a .emacs file exists in C:/
2800 If not, then we can try to default to the appdata directory under the
2801 user's profile, which is more likely to be writable. */
2802 if (sys_access ("C:/.emacs", F_OK
) != 0)
2804 HRESULT profile_result
;
2805 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2806 of Windows 95 and NT4 that have not been updated to include
2808 ShGetFolderPath_fn get_folder_path
;
2809 get_folder_path
= (ShGetFolderPath_fn
)
2810 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2812 if (get_folder_path
!= NULL
)
2814 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2817 /* If we can't get the appdata dir, revert to old behavior. */
2818 if (profile_result
== S_OK
)
2820 env_vars
[0].def_value
= default_home
;
2826 /* Get default locale info and use it for LANG. */
2827 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2828 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2829 locale_name
, sizeof (locale_name
)))
2831 for (i
= 0; i
< N_ENV_VARS
; i
++)
2833 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2835 env_vars
[i
].def_value
= locale_name
;
2841 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2843 /* Treat emacs_dir specially: set it unconditionally based on our
2847 char modname
[MAX_PATH
];
2849 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2851 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2855 if ((p
= _mbsrchr (modname
, '\\'))
2856 /* From bin means installed Emacs, from src means uninstalled. */
2857 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2859 char buf
[SET_ENV_BUF_SIZE
];
2860 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2863 for (p
= modname
; *p
; p
= CharNext (p
))
2864 if (*p
== '\\') *p
= '/';
2866 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2867 _putenv (strdup (buf
));
2868 /* If we are running from the Posix-like build tree, define
2869 SHELL to point to our own cmdproxy. The loop below will
2870 then disregard PATH_EXEC and the default value. */
2871 if (within_build_tree
)
2873 _snprintf (buf
, sizeof (buf
) - 1,
2874 "SHELL=%s/nt/cmdproxy.exe", modname
);
2875 _putenv (strdup (buf
));
2880 for (i
= 0; i
< N_ENV_VARS
; i
++)
2882 if (!getenv (env_vars
[i
].name
))
2885 char bufc
[SET_ENV_BUF_SIZE
];
2887 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2888 /* Also ignore empty environment variables. */
2893 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2895 /* Look for cmdproxy.exe in every directory in
2896 PATH_EXEC. FIXME: This does not find cmdproxy
2897 in nt/ when we run uninstalled. */
2898 char fname
[MAX_PATH
];
2899 const char *pstart
= PATH_EXEC
, *pend
;
2902 pend
= _mbschr (pstart
, ';');
2904 pend
= pstart
+ strlen (pstart
);
2905 /* Be defensive against series of ;;; characters. */
2908 strncpy (fname
, pstart
, pend
- pstart
);
2909 fname
[pend
- pstart
] = '/';
2910 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2911 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2913 if (sys_access (bufc
, F_OK
) == 0)
2926 /* If not found in any directory, use the
2927 default as the last resort. */
2928 lpval
= (char *)env_vars
[i
].def_value
;
2929 dwType
= REG_EXPAND_SZ
;
2935 lpval
= (char *)env_vars
[i
].def_value
;
2936 dwType
= REG_EXPAND_SZ
;
2938 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2939 Vdelayed_warnings_list
2941 (listn (CONSTYPE_HEAP
, 2,
2942 intern ("initialization"), build_string
2943 ("Use of `C:\\.emacs' without defining `HOME'\n"
2944 "in the environment is deprecated, "
2945 "see `Windows HOME' in the Emacs manual.")),
2946 Vdelayed_warnings_list
);
2951 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2953 if (dwType
== REG_EXPAND_SZ
)
2954 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2955 else if (dwType
== REG_SZ
)
2956 strcpy (buf1
, (char *)lpval
);
2957 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2959 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2961 _putenv (strdup (buf2
));
2971 /* Rebuild system configuration to reflect invoking system. */
2972 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2974 /* Another special case: on NT, the PATH variable is actually named
2975 "Path" although cmd.exe (perhaps NT itself) arranges for
2976 environment variable lookup and setting to be case insensitive.
2977 However, Emacs assumes a fully case sensitive environment, so we
2978 need to change "Path" to "PATH" to match the expectations of
2979 various elisp packages. We do this by the sneaky method of
2980 modifying the string in the C runtime environ entry.
2982 The same applies to COMSPEC. */
2985 const char *path
= "PATH=";
2986 int path_len
= strlen (path
);
2987 const char *comspec
= "COMSPEC=";
2988 int comspec_len
= strlen (comspec
);
2990 for (envp
= environ
; *envp
; envp
++)
2991 if (_strnicmp (*envp
, path
, path_len
) == 0)
2992 memcpy (*envp
, path
, path_len
);
2993 else if (_strnicmp (*envp
, comspec
, comspec_len
) == 0)
2994 memcpy (*envp
, comspec
, comspec_len
);
2996 /* Make the same modification to `process-environment' which has
2997 already been initialized in set_initial_environment. */
2998 for (Lisp_Object env
= Vprocess_environment
; CONSP (env
); env
= XCDR (env
))
3000 Lisp_Object entry
= XCAR (env
);
3001 if (_strnicmp (SDATA (entry
), path
, path_len
) == 0)
3002 for (int i
= 0; i
< path_len
; i
++)
3003 SSET (entry
, i
, path
[i
]);
3004 else if (_strnicmp (SDATA (entry
), comspec
, comspec_len
) == 0)
3005 for (int i
= 0; i
< comspec_len
; i
++)
3006 SSET (entry
, i
, comspec
[i
]);
3010 /* Remember the initial working directory for getcwd. */
3011 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
3012 Does it matter anywhere in Emacs? */
3013 if (w32_unicode_filenames
)
3015 wchar_t wstartup_dir
[MAX_PATH
];
3017 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
3019 filename_from_utf16 (wstartup_dir
, startup_dir
);
3023 char astartup_dir
[MAX_PATH
];
3025 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
3027 filename_from_ansi (astartup_dir
, startup_dir
);
3031 static char modname
[MAX_PATH
];
3033 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
3038 /* Determine if there is a middle mouse button, to allow parse_button
3039 to decide whether right mouse events should be mouse-2 or
3041 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
3046 /* Called from expand-file-name when default-directory is not a string. */
3049 emacs_root_dir (void)
3051 static char root_dir
[MAX_UTF8_PATH
];
3054 p
= getenv ("emacs_dir");
3057 filename_from_ansi (p
, root_dir
);
3058 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
3059 dostounix_filename (root_dir
);
3063 /* Emulate fdutimens. */
3065 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
3066 TIMESPEC[0] and TIMESPEC[1], respectively.
3067 FD must be either negative -- in which case it is ignored --
3068 or a file descriptor that is open on FILE.
3069 If FD is nonnegative, then FILE can be NULL, which means
3070 use just futimes instead of utimes.
3071 If TIMESPEC is null, FAIL.
3072 Return 0 on success, -1 (setting errno) on failure. */
3075 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
3082 if (fd
< 0 && !file
)
3087 /* _futime's prototype defines 2nd arg as having the type 'struct
3088 _utimbuf', while utime needs to accept 'struct utimbuf' for
3089 compatibility with Posix. So we need to use 2 different (but
3090 equivalent) types to avoid compiler warnings, sigh. */
3093 struct _utimbuf _ut
;
3095 _ut
.actime
= timespec
[0].tv_sec
;
3096 _ut
.modtime
= timespec
[1].tv_sec
;
3097 return _futime (fd
, &_ut
);
3103 ut
.actime
= timespec
[0].tv_sec
;
3104 ut
.modtime
= timespec
[1].tv_sec
;
3105 /* Call 'utime', which is implemented below, not the MS library
3106 function, which fails on directories. */
3107 return utime (file
, &ut
);
3112 /* ------------------------------------------------------------------------- */
3113 /* IO support and wrapper functions for the Windows API. */
3114 /* ------------------------------------------------------------------------- */
3116 /* Place a wrapper around the MSVC version of ctime. It returns NULL
3117 on network directories, so we handle that case here.
3118 (Ulrich Leodolter, 1/11/95). */
3120 sys_ctime (const time_t *t
)
3122 char *str
= (char *) ctime (t
);
3123 return (str
? str
: (char *)"Sun Jan 01 00:00:00 1970");
3126 /* Emulate sleep...we could have done this with a define, but that
3127 would necessitate including windows.h in the files that used it.
3128 This is much easier. */
3130 sys_sleep (int seconds
)
3132 Sleep (seconds
* 1000);
3135 /* Internal MSVC functions for low-level descriptor munging */
3136 extern int __cdecl
_set_osfhnd (int fd
, long h
);
3137 extern int __cdecl
_free_osfhnd (int fd
);
3139 /* parallel array of private info on file handles */
3140 filedesc fd_info
[ MAXDESC
];
3142 typedef struct volume_info_data
{
3143 struct volume_info_data
* next
;
3145 /* time when info was obtained */
3148 /* actual volume info */
3157 /* Global referenced by various functions. */
3158 static volume_info_data volume_info
;
3160 /* Vector to indicate which drives are local and fixed (for which cached
3161 data never expires). */
3162 static BOOL fixed_drives
[26];
3164 /* Consider cached volume information to be stale if older than 10s,
3165 at least for non-local drives. Info for fixed drives is never stale. */
3166 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3167 #define VOLINFO_STILL_VALID( root_dir, info ) \
3168 ( ( isalpha (root_dir[0]) && \
3169 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3170 || GetTickCount () - info->timestamp < 10000 )
3172 /* Cache support functions. */
3174 /* Simple linked list with linear search is sufficient. */
3175 static volume_info_data
*volume_cache
= NULL
;
3177 static volume_info_data
*
3178 lookup_volume_info (char * root_dir
)
3180 volume_info_data
* info
;
3182 for (info
= volume_cache
; info
; info
= info
->next
)
3183 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
3189 add_volume_info (char * root_dir
, volume_info_data
* info
)
3191 info
->root_dir
= xstrdup (root_dir
);
3192 unixtodos_filename (info
->root_dir
);
3193 info
->next
= volume_cache
;
3194 volume_cache
= info
;
3198 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3199 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3200 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3201 static volume_info_data
*
3202 GetCachedVolumeInformation (char * root_dir
)
3204 volume_info_data
* info
;
3205 char default_root
[ MAX_UTF8_PATH
];
3206 char name
[MAX_PATH
+1];
3207 char type
[MAX_PATH
+1];
3209 /* NULL for root_dir means use root from current directory. */
3210 if (root_dir
== NULL
)
3212 if (w32_unicode_filenames
)
3214 wchar_t curdirw
[MAX_PATH
];
3216 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3218 filename_from_utf16 (curdirw
, default_root
);
3222 char curdira
[MAX_PATH
];
3224 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3226 filename_from_ansi (curdira
, default_root
);
3228 parse_root (default_root
, (const char **)&root_dir
);
3230 root_dir
= default_root
;
3233 /* Local fixed drives can be cached permanently. Removable drives
3234 cannot be cached permanently, since the volume name and serial
3235 number (if nothing else) can change. Remote drives should be
3236 treated as if they are removable, since there is no sure way to
3237 tell whether they are or not. Also, the UNC association of drive
3238 letters mapped to remote volumes can be changed at any time (even
3239 by other processes) without notice.
3241 As a compromise, so we can benefit from caching info for remote
3242 volumes, we use a simple expiry mechanism to invalidate cache
3243 entries that are more than ten seconds old. */
3246 /* No point doing this, because WNetGetConnection is even slower than
3247 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3248 GetDriveType is about the only call of this type which does not
3249 involve network access, and so is extremely quick). */
3251 /* Map drive letter to UNC if remote. */
3252 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3254 char remote_name
[ 256 ];
3255 char drive
[3] = { root_dir
[0], ':' };
3257 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3259 /* do something */ ;
3263 info
= lookup_volume_info (root_dir
);
3265 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3271 /* Info is not cached, or is stale. */
3272 if (w32_unicode_filenames
)
3274 wchar_t root_w
[MAX_PATH
];
3275 wchar_t name_w
[MAX_PATH
+1];
3276 wchar_t type_w
[MAX_PATH
+1];
3278 filename_to_utf16 (root_dir
, root_w
);
3279 if (!GetVolumeInformationW (root_w
,
3280 name_w
, sizeof (name_w
),
3284 type_w
, sizeof (type_w
)))
3286 /* Hmm... not really 100% correct, as these 2 are not file
3288 filename_from_utf16 (name_w
, name
);
3289 filename_from_utf16 (type_w
, type
);
3293 char root_a
[MAX_PATH
];
3294 char name_a
[MAX_PATH
+1];
3295 char type_a
[MAX_PATH
+1];
3297 filename_to_ansi (root_dir
, root_a
);
3298 if (!GetVolumeInformationA (root_a
,
3299 name_a
, sizeof (name_a
),
3303 type_a
, sizeof (type_a
)))
3305 filename_from_ansi (name_a
, name
);
3306 filename_from_ansi (type_a
, type
);
3309 /* Cache the volume information for future use, overwriting existing
3310 entry if present. */
3313 info
= xmalloc (sizeof (volume_info_data
));
3314 add_volume_info (root_dir
, info
);
3322 info
->name
= xstrdup (name
);
3323 unixtodos_filename (info
->name
);
3324 info
->serialnum
= serialnum
;
3325 info
->maxcomp
= maxcomp
;
3326 info
->flags
= flags
;
3327 info
->type
= xstrdup (type
);
3328 info
->timestamp
= GetTickCount ();
3334 /* Get information on the volume where NAME is held; set path pointer to
3335 start of pathname in NAME (past UNC header\volume header if present),
3336 if pPath is non-NULL.
3338 Note: if NAME includes symlinks, the information is for the volume
3339 of the symlink, not of its target. That's because, even though
3340 GetVolumeInformation returns information about the symlink target
3341 of its argument, we only pass the root directory to
3342 GetVolumeInformation, not the full NAME. */
3344 get_volume_info (const char * name
, const char ** pPath
)
3346 char temp
[MAX_UTF8_PATH
];
3347 char *rootname
= NULL
; /* default to current volume */
3348 volume_info_data
* info
;
3349 int root_len
= parse_root (name
, pPath
);
3354 /* Copy the root name of the volume, if given. */
3357 strncpy (temp
, name
, root_len
);
3358 temp
[root_len
] = '\0';
3359 unixtodos_filename (temp
);
3363 info
= GetCachedVolumeInformation (rootname
);
3366 /* Set global referenced by other functions. */
3367 volume_info
= *info
;
3373 /* Determine if volume is FAT format (ie. only supports short 8.3
3374 names); also set path pointer to start of pathname in name, if
3375 pPath is non-NULL. */
3377 is_fat_volume (const char * name
, const char ** pPath
)
3379 if (get_volume_info (name
, pPath
))
3380 return (volume_info
.maxcomp
== 12);
3384 /* Convert all slashes in a filename to backslashes, and map filename
3385 to a valid 8.3 name if necessary. The result is a pointer to a
3386 static buffer, so CAVEAT EMPTOR! */
3387 const char *map_w32_filename (const char *, const char **);
3390 map_w32_filename (const char * name
, const char ** pPath
)
3392 static char shortname
[MAX_UTF8_PATH
];
3393 char * str
= shortname
;
3396 const char * save_name
= name
;
3398 if (strlen (name
) >= sizeof (shortname
))
3400 /* Return a filename which will cause callers to fail. */
3401 strcpy (shortname
, "?");
3405 if (!fatal_error_in_progress
/* disable fancy processing during crash */
3406 && is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3408 register int left
= 8; /* maximum number of chars in part */
3409 register int extn
= 0; /* extension added? */
3410 register int dots
= 2; /* maximum number of dots allowed */
3413 *str
++ = *name
++; /* skip past UNC header */
3415 while ((c
= *name
++))
3422 *str
++ = (c
== ':' ? ':' : '\\');
3423 extn
= 0; /* reset extension flags */
3424 dots
= 2; /* max 2 dots */
3425 left
= 8; /* max length 8 for main part */
3430 /* Convert path components of the form .xxx to _xxx,
3431 but leave . and .. as they are. This allows .emacs
3432 to be read as _emacs, for example. */
3436 IS_DIRECTORY_SEP (*name
))
3451 extn
= 1; /* we've got an extension */
3452 left
= 3; /* 3 chars in extension */
3456 /* any embedded dots after the first are converted to _ */
3461 case '#': /* don't lose these, they're important */
3463 str
[-1] = c
; /* replace last character of part */
3467 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3469 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3471 dots
= 0; /* started a path component */
3480 strcpy (shortname
, name
);
3481 unixtodos_filename (shortname
);
3485 *pPath
= shortname
+ (path
- save_name
);
3491 is_exec (const char * name
)
3493 char * p
= strrchr (name
, '.');
3496 && (xstrcasecmp (p
, ".exe") == 0 ||
3497 xstrcasecmp (p
, ".com") == 0 ||
3498 xstrcasecmp (p
, ".bat") == 0 ||
3499 xstrcasecmp (p
, ".cmd") == 0));
3502 /* Emulate the Unix directory procedures opendir, closedir, and
3503 readdir. We rename them to sys_* names because some versions of
3504 MinGW startup code call opendir and readdir to glob wildcards, and
3505 the code that calls them doesn't grok UTF-8 encoded file names we
3506 produce in dirent->d_name[]. */
3508 struct dirent dir_static
; /* simulated directory contents */
3509 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3510 static int dir_is_fat
;
3511 static char dir_pathname
[MAX_UTF8_PATH
];
3512 static WIN32_FIND_DATAW dir_find_data_w
;
3513 static WIN32_FIND_DATAA dir_find_data_a
;
3514 #define DIR_FIND_DATA_W 1
3515 #define DIR_FIND_DATA_A 2
3516 static int last_dir_find_data
= -1;
3518 /* Support shares on a network resource as subdirectories of a read-only
3520 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3521 static HANDLE
open_unc_volume (const char *);
3522 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3523 static void close_unc_volume (HANDLE
);
3526 sys_opendir (const char *filename
)
3530 /* Opening is done by FindFirstFile. However, a read is inherent to
3531 this operation, so we defer the open until read time. */
3533 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3535 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3538 /* Note: We don't support traversal of UNC volumes via symlinks.
3539 Doing so would mean punishing 99.99% of use cases by resolving
3540 all the possible symlinks in FILENAME, recursively. */
3541 if (is_unc_volume (filename
))
3543 wnet_enum_handle
= open_unc_volume (filename
);
3544 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3548 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3555 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3556 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3557 /* Note: We don't support symlinks to file names on FAT volumes.
3558 Doing so would mean punishing 99.99% of use cases by resolving
3559 all the possible symlinks in FILENAME, recursively. */
3560 dir_is_fat
= is_fat_volume (filename
, NULL
);
3566 sys_closedir (DIR *dirp
)
3568 /* If we have a find-handle open, close it. */
3569 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3571 FindClose (dir_find_handle
);
3572 dir_find_handle
= INVALID_HANDLE_VALUE
;
3574 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3576 close_unc_volume (wnet_enum_handle
);
3577 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3579 xfree ((char *) dirp
);
3583 sys_readdir (DIR *dirp
)
3585 int downcase
= !NILP (Vw32_downcase_file_names
);
3587 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3589 if (!read_unc_volume (wnet_enum_handle
,
3590 dir_find_data_w
.cFileName
,
3591 dir_find_data_a
.cFileName
,
3595 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3596 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3598 char filename
[MAX_UTF8_PATH
];
3600 bool last_slash
= true;
3602 /* Note: We don't need to worry about dir_pathname being longer
3603 than MAX_UTF8_PATH, as sys_opendir already took care of that
3604 when it called map_w32_filename: that function will put a "?"
3605 in its return value in that case, thus failing all the calls
3607 strcpy (filename
, dir_pathname
);
3608 ln
= strlen (filename
);
3609 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3612 /* Note: No need to resolve symlinks in FILENAME, because
3613 FindFirst opens the directory that is the target of a
3615 if (w32_unicode_filenames
)
3617 wchar_t fnw
[MAX_PATH
+ 2];
3619 filename_to_utf16 (filename
, fnw
);
3621 wcscat (fnw
, L
"\\");
3623 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3627 char fna
[MAX_PATH
+ 2];
3629 filename_to_ansi (filename
, fna
);
3633 /* If FILENAME is not representable by the current ANSI
3634 codepage, we don't want FindFirstFileA to interpret the
3635 '?' characters as a wildcard. */
3636 if (_mbspbrk (fna
, "?"))
3637 dir_find_handle
= INVALID_HANDLE_VALUE
;
3639 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3642 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3644 /* Any changes in the value of errno here should be in sync
3645 with what directory_files_internal does when it calls
3647 switch (GetLastError ())
3649 /* Windows uses this value when FindFirstFile finds no
3650 files that match the wildcard. This is not supposed
3651 to happen, since our wildcard is "*", but just in
3652 case, if there's some weird empty directory with not
3653 even "." and ".." entries... */
3654 case ERROR_FILE_NOT_FOUND
:
3659 case ERROR_ACCESS_DENIED
:
3660 case ERROR_NETWORK_ACCESS_DENIED
:
3663 case ERROR_PATH_NOT_FOUND
:
3664 case ERROR_INVALID_DRIVE
:
3665 case ERROR_NOT_READY
:
3666 case ERROR_BAD_NETPATH
:
3667 case ERROR_BAD_NET_NAME
:
3674 else if (w32_unicode_filenames
)
3676 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3684 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3691 /* Emacs never uses this value, so don't bother making it match
3692 value returned by stat(). */
3693 dir_static
.d_ino
= 1;
3695 if (w32_unicode_filenames
)
3697 if (downcase
|| dir_is_fat
)
3699 wchar_t tem
[MAX_PATH
];
3701 wcscpy (tem
, dir_find_data_w
.cFileName
);
3703 filename_from_utf16 (tem
, dir_static
.d_name
);
3706 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3707 last_dir_find_data
= DIR_FIND_DATA_W
;
3713 /* If the file name in cFileName[] includes `?' characters, it
3714 means the original file name used characters that cannot be
3715 represented by the current ANSI codepage. To avoid total
3716 lossage, retrieve the short 8+3 alias of the long file
3718 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3720 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3721 /* 8+3 aliases are returned in all caps, which could break
3722 various alists that look at filenames' extensions. */
3725 else if (downcase
|| dir_is_fat
)
3726 strcpy (tem
, dir_find_data_a
.cFileName
);
3728 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3729 if (downcase
|| dir_is_fat
)
3732 filename_from_ansi (tem
, dir_static
.d_name
);
3734 last_dir_find_data
= DIR_FIND_DATA_A
;
3737 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3738 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3739 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3745 open_unc_volume (const char *path
)
3747 const char *fn
= map_w32_filename (path
, NULL
);
3751 if (w32_unicode_filenames
)
3754 wchar_t fnw
[MAX_PATH
];
3756 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3757 nrw
.dwType
= RESOURCETYPE_DISK
;
3758 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3759 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3760 nrw
.lpLocalName
= NULL
;
3761 filename_to_utf16 (fn
, fnw
);
3762 nrw
.lpRemoteName
= fnw
;
3763 nrw
.lpComment
= NULL
;
3764 nrw
.lpProvider
= NULL
;
3766 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3767 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3774 nra
.dwScope
= RESOURCE_GLOBALNET
;
3775 nra
.dwType
= RESOURCETYPE_DISK
;
3776 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3777 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3778 nra
.lpLocalName
= NULL
;
3779 filename_to_ansi (fn
, fna
);
3780 nra
.lpRemoteName
= fna
;
3781 nra
.lpComment
= NULL
;
3782 nra
.lpProvider
= NULL
;
3784 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3785 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3787 if (result
== NO_ERROR
)
3791 /* Make sure directory_files_internal reports a sensible error. */
3793 return INVALID_HANDLE_VALUE
;
3798 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3803 DWORD bufsize
= 512;
3807 if (w32_unicode_filenames
)
3812 buffer
= alloca (bufsize
);
3813 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3814 if (result
!= NO_ERROR
)
3816 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3817 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3819 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3821 wcsncpy (fname_w
, ptrw
, size
);
3826 int dbcs_p
= max_filename_mbslen () > 1;
3829 buffer
= alloca (bufsize
);
3830 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3831 if (result
!= NO_ERROR
)
3833 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3836 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3839 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3840 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3843 strncpy (fname_a
, ptra
, size
);
3851 close_unc_volume (HANDLE henum
)
3853 if (henum
!= INVALID_HANDLE_VALUE
)
3854 WNetCloseEnum (henum
);
3858 unc_volume_file_attributes (const char *path
)
3863 henum
= open_unc_volume (path
);
3864 if (henum
== INVALID_HANDLE_VALUE
)
3867 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3869 close_unc_volume (henum
);
3874 /* Ensure a network connection is authenticated. */
3876 logon_network_drive (const char *path
)
3878 char share
[MAX_UTF8_PATH
];
3885 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3886 drvtype
= DRIVE_REMOTE
;
3887 else if (path
[0] == '\0' || path
[1] != ':')
3888 drvtype
= GetDriveType (NULL
);
3895 drvtype
= GetDriveType (drive
);
3898 /* Only logon to networked drives. */
3899 if (drvtype
!= DRIVE_REMOTE
)
3903 strncpy (share
, path
, MAX_UTF8_PATH
);
3904 /* Truncate to just server and share name. */
3905 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3907 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3914 if (w32_unicode_filenames
)
3916 NETRESOURCEW resourcew
;
3917 wchar_t share_w
[MAX_PATH
];
3919 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3920 resourcew
.dwType
= RESOURCETYPE_DISK
;
3921 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3922 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3923 resourcew
.lpLocalName
= NULL
;
3924 filename_to_utf16 (share
, share_w
);
3925 resourcew
.lpRemoteName
= share_w
;
3926 resourcew
.lpProvider
= NULL
;
3928 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3932 NETRESOURCEA resourcea
;
3933 char share_a
[MAX_PATH
];
3935 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3936 resourcea
.dwType
= RESOURCETYPE_DISK
;
3937 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3938 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3939 resourcea
.lpLocalName
= NULL
;
3940 filename_to_ansi (share
, share_a
);
3941 resourcea
.lpRemoteName
= share_a
;
3942 resourcea
.lpProvider
= NULL
;
3944 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3950 case ERROR_ALREADY_ASSIGNED
:
3952 case ERROR_ACCESS_DENIED
:
3953 case ERROR_LOGON_FAILURE
:
3959 case ERROR_BAD_NET_NAME
:
3960 case ERROR_NO_NET_OR_BAD_PATH
:
3961 case ERROR_NO_NETWORK
:
3962 case ERROR_CANCELLED
:
3969 /* Emulate faccessat(2). */
3971 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3974 char fullname
[MAX_UTF8_PATH
];
3976 /* Rely on a hack: an open directory is modeled as file descriptor 0,
3977 and its actual file name is stored in dir_pathname by opendir.
3978 This is good enough for the current usage in Emacs, but is fragile. */
3979 if (dirfd
!= AT_FDCWD
3980 && !(IS_DIRECTORY_SEP (path
[0])
3981 || IS_DEVICE_SEP (path
[1])))
3983 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
3985 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
3986 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", path
)
3989 errno
= ENAMETOOLONG
;
3995 /* When dired.c calls us with F_OK and a trailing slash, it actually
3996 wants to know whether PATH is a directory. */
3997 if (IS_DIRECTORY_SEP (path
[strlen (path
) - 1]) && mode
== F_OK
)
4000 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
4001 newer versions blow up when passed D_OK. */
4002 path
= map_w32_filename (path
, NULL
);
4003 /* If the last element of PATH is a symlink, we need to resolve it
4004 to get the attributes of its target file. Note: any symlinks in
4005 PATH elements other than the last one are transparently resolved
4006 by GetFileAttributes below. */
4007 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
4008 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
4009 path
= chase_symlinks (path
);
4011 if (w32_unicode_filenames
)
4013 wchar_t path_w
[MAX_PATH
];
4015 filename_to_utf16 (path
, path_w
);
4016 attributes
= GetFileAttributesW (path_w
);
4020 char path_a
[MAX_PATH
];
4022 filename_to_ansi (path
, path_a
);
4023 attributes
= GetFileAttributesA (path_a
);
4026 if (attributes
== -1)
4028 DWORD w32err
= GetLastError ();
4032 case ERROR_INVALID_NAME
:
4033 case ERROR_BAD_PATHNAME
:
4034 if (is_unc_volume (path
))
4036 attributes
= unc_volume_file_attributes (path
);
4037 if (attributes
== -1)
4046 case ERROR_FILE_NOT_FOUND
:
4047 case ERROR_BAD_NETPATH
:
4058 if ((mode
& X_OK
) != 0
4059 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4064 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4069 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4077 /* A special test for DIRNAME being a directory accessible by the
4078 current user. This is needed because the security permissions in
4079 directory's ACLs are not visible in the Posix-style mode bits
4080 returned by 'stat' and in attributes returned by GetFileAttributes.
4081 So a directory would seem like it's readable by the current user,
4082 but will in fact error out with EACCES when they actually try. */
4084 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
4086 char pattern
[MAX_UTF8_PATH
];
4087 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
4090 /* Network volumes need a different reading method. */
4091 if (is_unc_volume (dirname
))
4093 void *read_result
= NULL
;
4094 wchar_t fnw
[MAX_PATH
];
4097 dh
= open_unc_volume (dirname
);
4098 if (dh
!= INVALID_HANDLE_VALUE
)
4100 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
4101 close_unc_volume (dh
);
4103 /* Treat empty volumes as accessible. */
4104 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
4107 /* Note: map_w32_filename makes sure DIRNAME is not longer than
4109 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
4111 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
4112 opens the directory that is the target of a symlink. */
4113 if (w32_unicode_filenames
)
4115 wchar_t pat_w
[MAX_PATH
+ 2];
4116 WIN32_FIND_DATAW dfd_w
;
4118 filename_to_utf16 (pattern
, pat_w
);
4120 wcscat (pat_w
, L
"\\");
4121 wcscat (pat_w
, L
"*");
4122 dh
= FindFirstFileW (pat_w
, &dfd_w
);
4126 char pat_a
[MAX_PATH
+ 2];
4127 WIN32_FIND_DATAA dfd_a
;
4129 filename_to_ansi (pattern
, pat_a
);
4131 strcpy (pat_a
, "\\");
4132 strcat (pat_a
, "*");
4133 /* In case DIRNAME cannot be expressed in characters from the
4134 current ANSI codepage. */
4135 if (_mbspbrk (pat_a
, "?"))
4136 dh
= INVALID_HANDLE_VALUE
;
4138 dh
= FindFirstFileA (pat_a
, &dfd_a
);
4141 if (dh
== INVALID_HANDLE_VALUE
)
4147 /* A version of 'access' to be used locally with file names in
4148 locale-specific encoding. Does not resolve symlinks and does not
4149 support file names on FAT12 and FAT16 volumes, but that's OK, since
4150 we only invoke this function for files inside the Emacs source or
4151 installation tree, on directories (so any symlinks should have the
4152 directory bit set), and on short file names such as "C:/.emacs". */
4154 sys_access (const char *fname
, int mode
)
4156 char fname_copy
[MAX_PATH
], *p
;
4159 strcpy (fname_copy
, fname
);
4160 /* Do the equivalent of unixtodos_filename. */
4161 for (p
= fname_copy
; *p
; p
= CharNext (p
))
4165 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
4167 DWORD w32err
= GetLastError ();
4171 case ERROR_INVALID_NAME
:
4172 case ERROR_BAD_PATHNAME
:
4173 case ERROR_FILE_NOT_FOUND
:
4174 case ERROR_BAD_NETPATH
:
4183 if ((mode
& X_OK
) != 0
4184 && !(is_exec (fname_copy
)
4185 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
4190 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
4195 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
4203 /* Shadow some MSVC runtime functions to map requests for long filenames
4204 to reasonable short names if necessary. This was originally added to
4205 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
4209 sys_chdir (const char * path
)
4211 path
= map_w32_filename (path
, NULL
);
4212 if (w32_unicode_filenames
)
4214 wchar_t newdir_w
[MAX_PATH
];
4216 if (filename_to_utf16 (path
, newdir_w
) == 0)
4217 return _wchdir (newdir_w
);
4222 char newdir_a
[MAX_PATH
];
4224 if (filename_to_ansi (path
, newdir_a
) == 0)
4225 return _chdir (newdir_a
);
4231 sys_chmod (const char * path
, int mode
)
4233 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4234 if (w32_unicode_filenames
)
4236 wchar_t path_w
[MAX_PATH
];
4238 filename_to_utf16 (path
, path_w
);
4239 return _wchmod (path_w
, mode
);
4243 char path_a
[MAX_PATH
];
4245 filename_to_ansi (path
, path_a
);
4246 return _chmod (path_a
, mode
);
4251 sys_creat (const char * path
, int mode
)
4253 path
= map_w32_filename (path
, NULL
);
4254 if (w32_unicode_filenames
)
4256 wchar_t path_w
[MAX_PATH
];
4258 filename_to_utf16 (path
, path_w
);
4259 return _wcreat (path_w
, mode
);
4263 char path_a
[MAX_PATH
];
4265 filename_to_ansi (path
, path_a
);
4266 return _creat (path_a
, mode
);
4271 sys_fopen (const char * path
, const char * mode
)
4275 const char * mode_save
= mode
;
4277 /* Force all file handles to be non-inheritable. This is necessary to
4278 ensure child processes don't unwittingly inherit handles that might
4279 prevent future file access. */
4283 else if (mode
[0] == 'w' || mode
[0] == 'a')
4284 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4288 /* Only do simplistic option parsing. */
4292 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4295 else if (mode
[0] == 'b')
4300 else if (mode
[0] == 't')
4307 path
= map_w32_filename (path
, NULL
);
4308 if (w32_unicode_filenames
)
4310 wchar_t path_w
[MAX_PATH
];
4312 filename_to_utf16 (path
, path_w
);
4313 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4317 char path_a
[MAX_PATH
];
4319 filename_to_ansi (path
, path_a
);
4320 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4325 return _fdopen (fd
, mode_save
);
4328 /* This only works on NTFS volumes, but is useful to have. */
4330 sys_link (const char * old
, const char * new)
4334 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4335 wchar_t oldname_w
[MAX_PATH
];
4336 char oldname_a
[MAX_PATH
];
4338 if (old
== NULL
|| new == NULL
)
4344 strcpy (oldname
, map_w32_filename (old
, NULL
));
4345 strcpy (newname
, map_w32_filename (new, NULL
));
4347 if (w32_unicode_filenames
)
4349 filename_to_utf16 (oldname
, oldname_w
);
4350 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4351 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4355 filename_to_ansi (oldname
, oldname_a
);
4356 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4357 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4359 if (fileh
!= INVALID_HANDLE_VALUE
)
4363 /* Confusingly, the "alternate" stream name field does not apply
4364 when restoring a hard link, and instead contains the actual
4365 stream data for the link (ie. the name of the link to create).
4366 The WIN32_STREAM_ID structure before the cStreamName field is
4367 the stream header, which is then immediately followed by the
4371 WIN32_STREAM_ID wid
;
4372 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4375 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4376 indicates that flag is unsupported for CP_UTF8, and OTOH says
4377 it is the default anyway. */
4378 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4379 data
.wid
.cStreamName
, MAX_PATH
);
4382 LPVOID context
= NULL
;
4385 data
.wid
.dwStreamId
= BACKUP_LINK
;
4386 data
.wid
.dwStreamAttributes
= 0;
4387 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4388 data
.wid
.Size
.HighPart
= 0;
4389 data
.wid
.dwStreamNameSize
= 0;
4391 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4392 offsetof (WIN32_STREAM_ID
, cStreamName
)
4393 + data
.wid
.Size
.LowPart
,
4394 &wbytes
, FALSE
, FALSE
, &context
)
4395 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4402 DWORD err
= GetLastError ();
4407 case ERROR_ACCESS_DENIED
:
4408 /* This is what happens when OLDNAME is a directory,
4409 since Windows doesn't support hard links to
4410 directories. Posix says to set errno to EPERM in
4412 if (w32_unicode_filenames
)
4413 attributes
= GetFileAttributesW (oldname_w
);
4415 attributes
= GetFileAttributesA (oldname_a
);
4416 if (attributes
!= -1
4417 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4419 else if (attributes
== -1
4420 && is_unc_volume (oldname
)
4421 && unc_volume_file_attributes (oldname
) != -1)
4426 case ERROR_TOO_MANY_LINKS
:
4429 case ERROR_NOT_SAME_DEVICE
:
4439 CloseHandle (fileh
);
4448 sys_mkdir (const char * path
, mode_t mode
)
4450 path
= map_w32_filename (path
, NULL
);
4452 if (w32_unicode_filenames
)
4454 wchar_t path_w
[MAX_PATH
];
4456 filename_to_utf16 (path
, path_w
);
4457 return _wmkdir (path_w
);
4461 char path_a
[MAX_PATH
];
4463 filename_to_ansi (path
, path_a
);
4464 return _mkdir (path_a
);
4469 sys_open (const char * path
, int oflag
, int mode
)
4471 const char* mpath
= map_w32_filename (path
, NULL
);
4474 if (w32_unicode_filenames
)
4476 wchar_t mpath_w
[MAX_PATH
];
4478 filename_to_utf16 (mpath
, mpath_w
);
4479 /* If possible, try to open file without _O_CREAT, to be able to
4480 write to existing hidden and system files. Force all file
4481 handles to be non-inheritable. */
4482 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4483 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4485 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4489 char mpath_a
[MAX_PATH
];
4491 filename_to_ansi (mpath
, mpath_a
);
4492 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4493 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4495 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4502 fchmod (int fd
, mode_t mode
)
4508 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4511 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4514 bool have_temp_a
= false;
4516 /* MoveFile on Windows 95 doesn't correctly change the short file name
4517 alias in a number of circumstances (it is not easy to predict when
4518 just by looking at oldname and newname, unfortunately). In these
4519 cases, renaming through a temporary name avoids the problem.
4521 A second problem on Windows 95 is that renaming through a temp name when
4522 newname is uppercase fails (the final long name ends up in
4523 lowercase, although the short alias might be uppercase) UNLESS the
4524 long temp name is not 8.3.
4526 So, on Windows 95 we always rename through a temp name, and we make sure
4527 the temp name has a long extension to ensure correct renaming. */
4529 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4531 /* volume_info is set indirectly by map_w32_filename. */
4532 oldname_dev
= volume_info
.serialnum
;
4534 if (os_subtype
== OS_9X
)
4539 char oldname_a
[MAX_PATH
];
4541 oldname
= map_w32_filename (oldname
, NULL
);
4542 filename_to_ansi (oldname
, oldname_a
);
4543 filename_to_ansi (temp
, temp_a
);
4544 if ((o
= strrchr (oldname_a
, '\\')))
4547 o
= (char *) oldname_a
;
4549 if ((p
= strrchr (temp_a
, '\\')))
4556 /* Force temp name to require a manufactured 8.3 alias - this
4557 seems to make the second rename work properly. */
4558 sprintf (p
, "_.%s.%d", o
, i
);
4560 result
= rename (oldname_a
, temp_a
);
4562 /* This loop must surely terminate! */
4563 while (result
< 0 && errno
== EEXIST
);
4569 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4570 (at least if it is a file; don't do this for directories).
4572 Since we mustn't do this if we are just changing the case of the
4573 file name (we would end up deleting the file we are trying to
4574 rename!), we let rename detect if the destination file already
4575 exists - that way we avoid the possible pitfalls of trying to
4576 determine ourselves whether two names really refer to the same
4577 file, which is not always possible in the general case. (Consider
4578 all the permutations of shared or subst'd drives, etc.) */
4580 newname
= map_w32_filename (newname
, NULL
);
4582 /* volume_info is set indirectly by map_w32_filename. */
4583 newname_dev
= volume_info
.serialnum
;
4585 if (w32_unicode_filenames
)
4587 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4589 filename_to_utf16 (temp
, temp_w
);
4590 filename_to_utf16 (newname
, newname_w
);
4591 result
= _wrename (temp_w
, newname_w
);
4594 DWORD w32err
= GetLastError ();
4597 && newname_dev
!= oldname_dev
)
4600 /* The implementation of `rename' on Windows does not return
4601 errno = EXDEV when you are moving a directory to a
4602 different storage device (ex. logical disk). It returns
4603 EACCES instead. So here we handle such situations and
4605 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4606 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4609 else if (errno
== EEXIST
&& force
)
4611 DWORD attributes_old
;
4612 DWORD attributes_new
;
4614 if (_wchmod (newname_w
, 0666) != 0)
4616 attributes_old
= GetFileAttributesW (temp_w
);
4617 attributes_new
= GetFileAttributesW (newname_w
);
4618 if (attributes_old
!= -1 && attributes_new
!= -1
4619 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4620 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4622 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4628 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4630 if (_wrmdir (newname_w
) != 0)
4633 else if (_wunlink (newname_w
) != 0)
4635 result
= _wrename (temp_w
, newname_w
);
4637 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4638 && is_symlink (temp
))
4640 /* This is Windows prohibiting the user from creating a
4641 symlink in another place, since that requires
4649 char newname_a
[MAX_PATH
];
4652 filename_to_ansi (temp
, temp_a
);
4653 filename_to_ansi (newname
, newname_a
);
4654 result
= rename (temp_a
, newname_a
);
4657 DWORD w32err
= GetLastError ();
4660 && newname_dev
!= oldname_dev
)
4663 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4664 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4667 else if (errno
== EEXIST
&& force
)
4669 DWORD attributes_old
;
4670 DWORD attributes_new
;
4672 if (_chmod (newname_a
, 0666) != 0)
4674 attributes_old
= GetFileAttributesA (temp_a
);
4675 attributes_new
= GetFileAttributesA (newname_a
);
4676 if (attributes_old
!= -1 && attributes_new
!= -1
4677 && ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
)
4678 != (attributes_new
& FILE_ATTRIBUTE_DIRECTORY
)))
4680 if ((attributes_old
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4686 if ((attributes_new
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4688 if (_rmdir (newname_a
) != 0)
4691 else if (_unlink (newname_a
) != 0)
4693 result
= rename (temp_a
, newname_a
);
4695 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4696 && is_symlink (temp
))
4705 sys_rename (char const *old
, char const *new)
4707 return sys_rename_replace (old
, new, TRUE
);
4711 sys_rmdir (const char * path
)
4713 path
= map_w32_filename (path
, NULL
);
4715 if (w32_unicode_filenames
)
4717 wchar_t path_w
[MAX_PATH
];
4719 filename_to_utf16 (path
, path_w
);
4720 return _wrmdir (path_w
);
4724 char path_a
[MAX_PATH
];
4726 filename_to_ansi (path
, path_a
);
4727 return _rmdir (path_a
);
4732 sys_unlink (const char * path
)
4736 path
= map_w32_filename (path
, NULL
);
4738 if (w32_unicode_filenames
)
4740 wchar_t path_w
[MAX_PATH
];
4742 filename_to_utf16 (path
, path_w
);
4743 /* On Unix, unlink works without write permission. */
4744 _wchmod (path_w
, 0666);
4745 rmstatus
= _wunlink (path_w
);
4747 /* Symlinks to directories can only be deleted by _rmdir;
4748 _unlink returns EACCES. */
4751 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4752 rmstatus
= _wrmdir (path_w
);
4758 char path_a
[MAX_PATH
];
4760 filename_to_ansi (path
, path_a
);
4761 _chmod (path_a
, 0666);
4762 rmstatus
= _unlink (path_a
);
4766 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4767 rmstatus
= _rmdir (path_a
);
4775 static FILETIME utc_base_ft
;
4776 static ULONGLONG utc_base
; /* In 100ns units */
4777 static int init
= 0;
4779 #define FILETIME_TO_U64(result, ft) \
4781 ULARGE_INTEGER uiTemp; \
4782 uiTemp.LowPart = (ft).dwLowDateTime; \
4783 uiTemp.HighPart = (ft).dwHighDateTime; \
4784 result = uiTemp.QuadPart; \
4788 initialize_utc_base (void)
4790 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4799 st
.wMilliseconds
= 0;
4801 SystemTimeToFileTime (&st
, &utc_base_ft
);
4802 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4806 convert_time (FILETIME ft
)
4812 initialize_utc_base ();
4816 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4819 FILETIME_TO_U64 (tmp
, ft
);
4820 return (time_t) ((tmp
- utc_base
) / 10000000L);
4824 convert_from_time_t (time_t time
, FILETIME
* pft
)
4830 initialize_utc_base ();
4834 /* time in 100ns units since 1-Jan-1601 */
4835 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4836 pft
->dwHighDateTime
= tmp
.HighPart
;
4837 pft
->dwLowDateTime
= tmp
.LowPart
;
4840 static PSECURITY_DESCRIPTOR
4841 get_file_security_desc_by_handle (HANDLE h
)
4843 PSECURITY_DESCRIPTOR psd
= NULL
;
4845 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4846 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4848 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4849 NULL
, NULL
, NULL
, NULL
, &psd
);
4850 if (err
!= ERROR_SUCCESS
)
4856 static PSECURITY_DESCRIPTOR
4857 get_file_security_desc_by_name (const char *fname
)
4859 PSECURITY_DESCRIPTOR psd
= NULL
;
4861 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4862 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4864 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4866 err
= GetLastError ();
4867 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4871 psd
= xmalloc (sd_len
);
4872 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4884 unsigned n_subauthorities
;
4886 /* Use the last sub-authority value of the RID, the relative
4887 portion of the SID, as user/group ID. */
4888 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4889 if (n_subauthorities
< 1)
4890 return 0; /* the "World" RID */
4891 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4894 /* Caching SID and account values for faster lokup. */
4898 struct w32_id
*next
;
4900 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4903 static struct w32_id
*w32_idlist
;
4906 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4908 struct w32_id
*tail
, *found
;
4910 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4912 if (equal_sid ((PSID
)tail
->sid
, sid
))
4921 strcpy (name
, found
->name
);
4929 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4932 struct w32_id
*new_entry
;
4934 /* We don't want to leave behind stale cache from when Emacs was
4938 sid_len
= get_length_sid (sid
);
4939 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4942 new_entry
->rid
= id
;
4943 strcpy (new_entry
->name
, name
);
4944 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4945 new_entry
->next
= w32_idlist
;
4946 w32_idlist
= new_entry
;
4955 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4959 SID_NAME_USE ignore
;
4961 DWORD name_len
= sizeof (name
);
4963 DWORD domain_len
= sizeof (domain
);
4968 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4969 else if (what
== GID
)
4970 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4974 if (!result
|| !is_valid_sid (sid
))
4976 else if (!w32_cached_id (sid
, id
, nm
))
4978 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4979 domain
, &domain_len
, &ignore
)
4980 || name_len
> UNLEN
+1)
4984 *id
= get_rid (sid
);
4986 w32_add_to_cache (sid
, *id
, name
);
4993 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4995 int dflt_usr
= 0, dflt_grp
= 0;
5004 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
5006 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
5009 /* Consider files to belong to current user/group, if we cannot get
5010 more accurate information. */
5013 st
->st_uid
= dflt_passwd
.pw_uid
;
5014 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
5018 st
->st_gid
= dflt_passwd
.pw_gid
;
5019 strcpy (st
->st_gname
, dflt_group
.gr_name
);
5023 /* Return non-zero if NAME is a potentially slow filesystem. */
5024 int is_slow_fs (const char *);
5027 is_slow_fs (const char *name
)
5032 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
5033 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
5034 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
5035 devtype
= GetDriveType (NULL
); /* use root of current drive */
5038 /* GetDriveType needs the root directory of the drive. */
5039 strncpy (drive_root
, name
, 2);
5040 drive_root
[2] = '\\';
5041 drive_root
[3] = '\0';
5042 devtype
= GetDriveType (drive_root
);
5044 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
5047 /* If this is non-zero, the caller wants accurate information about
5048 file's owner and group, which could be expensive to get. dired.c
5049 uses this flag when needed for the job at hand. */
5050 int w32_stat_get_owner_group
;
5052 /* MSVC stat function can't cope with UNC names and has other bugs, so
5053 replace it with our own. This also allows us to calculate consistent
5054 inode values and owner/group without hacks in the main Emacs code,
5055 and support file names encoded in UTF-8. */
5058 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
5060 char *name
, *save_name
, *r
;
5061 WIN32_FIND_DATAW wfd_w
;
5062 WIN32_FIND_DATAA wfd_a
;
5064 unsigned __int64 fake_inode
= 0;
5067 int rootdir
= FALSE
;
5068 PSECURITY_DESCRIPTOR psd
= NULL
;
5069 int is_a_symlink
= 0;
5070 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
5071 DWORD access_rights
= 0;
5072 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
5073 FILETIME ctime
, atime
, wtime
;
5074 wchar_t name_w
[MAX_PATH
];
5075 char name_a
[MAX_PATH
];
5077 if (path
== NULL
|| buf
== NULL
)
5083 save_name
= name
= (char *) map_w32_filename (path
, &path
);
5084 /* Must be valid filename, no wild cards or other invalid
5086 if (strpbrk (name
, "*?|<>\""))
5092 len
= strlen (name
);
5093 /* Allocate 1 extra byte so that we could append a slash to a root
5094 directory, down below. */
5095 name
= strcpy (alloca (len
+ 2), name
);
5097 /* Avoid a somewhat costly call to is_symlink if the filesystem
5098 doesn't support symlinks. */
5099 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5100 is_a_symlink
= is_symlink (name
);
5102 /* Plan A: Open the file and get all the necessary information via
5103 the resulting handle. This solves several issues in one blow:
5105 . retrieves attributes for the target of a symlink, if needed
5106 . gets attributes of root directories and symlinks pointing to
5107 root directories, thus avoiding the need for special-casing
5108 these and detecting them by examining the file-name format
5109 . retrieves more accurate attributes (e.g., non-zero size for
5110 some directories, esp. directories that are junction points)
5111 . correctly resolves "c:/..", "/.." and similar file names
5112 . avoids run-time penalties for 99% of use cases
5114 Plan A is always tried first, unless the user asked not to (but
5115 if the file is a symlink and we need to follow links, we try Plan
5116 A even if the user asked not to).
5118 If Plan A fails, we go to Plan B (below), where various
5119 potentially expensive techniques must be used to handle "special"
5120 files such as UNC volumes etc. */
5121 if (!(NILP (Vw32_get_true_file_attributes
)
5122 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
5123 /* Following symlinks requires getting the info by handle. */
5124 || (is_a_symlink
&& follow_symlinks
))
5126 BY_HANDLE_FILE_INFORMATION info
;
5128 if (is_a_symlink
&& !follow_symlinks
)
5129 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
5130 /* READ_CONTROL access rights are required to get security info
5131 by handle. But if the OS doesn't support security in the
5132 first place, we don't need to try. */
5133 if (is_windows_9x () != TRUE
)
5134 access_rights
|= READ_CONTROL
;
5136 if (w32_unicode_filenames
)
5138 filename_to_utf16 (name
, name_w
);
5139 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5141 /* If CreateFile fails with READ_CONTROL, try again with
5142 zero as access rights. */
5143 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5144 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
5149 filename_to_ansi (name
, name_a
);
5150 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
5152 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
5153 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
5156 if (fh
== INVALID_HANDLE_VALUE
)
5157 goto no_true_file_attributes
;
5159 /* This is more accurate in terms of getting the correct number
5160 of links, but is quite slow (it is noticeable when Emacs is
5161 making a list of file name completions). */
5162 if (GetFileInformationByHandle (fh
, &info
))
5164 nlinks
= info
.nNumberOfLinks
;
5165 /* Might as well use file index to fake inode values, but this
5166 is not guaranteed to be unique unless we keep a handle open
5167 all the time (even then there are situations where it is
5168 not unique). Reputedly, there are at most 48 bits of info
5169 (on NTFS, presumably less on FAT). */
5170 fake_inode
= info
.nFileIndexHigh
;
5172 fake_inode
+= info
.nFileIndexLow
;
5173 serialnum
= info
.dwVolumeSerialNumber
;
5174 fs_high
= info
.nFileSizeHigh
;
5175 fs_low
= info
.nFileSizeLow
;
5176 ctime
= info
.ftCreationTime
;
5177 atime
= info
.ftLastAccessTime
;
5178 wtime
= info
.ftLastWriteTime
;
5179 fattrs
= info
.dwFileAttributes
;
5183 /* We don't go to Plan B here, because it's not clear that
5184 it's a good idea. The only known use case where
5185 CreateFile succeeds, but GetFileInformationByHandle fails
5186 (with ERROR_INVALID_FUNCTION) is for character devices
5187 such as NUL, PRN, etc. For these, switching to Plan B is
5188 a net loss, because we lose the character device
5189 attribute returned by GetFileType below (FindFirstFile
5190 doesn't set that bit in the attributes), and the other
5191 fields don't make sense for character devices anyway.
5192 Emacs doesn't really care for non-file entities in the
5193 context of l?stat, so neither do we. */
5195 /* w32err is assigned so one could put a breakpoint here and
5196 examine its value, when GetFileInformationByHandle
5198 DWORD w32err
= GetLastError ();
5202 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5208 /* Test for a symlink before testing for a directory, since
5209 symlinks to directories have the directory bit set, but we
5210 don't want them to appear as directories. */
5211 if (is_a_symlink
&& !follow_symlinks
)
5212 buf
->st_mode
= S_IFLNK
;
5213 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5214 buf
->st_mode
= S_IFDIR
;
5217 DWORD ftype
= GetFileType (fh
);
5221 case FILE_TYPE_DISK
:
5222 buf
->st_mode
= S_IFREG
;
5224 case FILE_TYPE_PIPE
:
5225 buf
->st_mode
= S_IFIFO
;
5227 case FILE_TYPE_CHAR
:
5228 case FILE_TYPE_UNKNOWN
:
5230 buf
->st_mode
= S_IFCHR
;
5233 /* We produce the fallback owner and group data, based on the
5234 current user that runs Emacs, in the following cases:
5236 . caller didn't request owner and group info
5237 . this is Windows 9X
5238 . getting security by handle failed, and we need to produce
5239 information for the target of a symlink (this is better
5240 than producing a potentially misleading info about the
5243 If getting security by handle fails, and we don't need to
5244 resolve symlinks, we try getting security by name. */
5245 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5246 get_file_owner_and_group (NULL
, buf
);
5249 psd
= get_file_security_desc_by_handle (fh
);
5252 get_file_owner_and_group (psd
, buf
);
5255 else if (!(is_a_symlink
&& follow_symlinks
))
5257 psd
= get_file_security_desc_by_name (name
);
5258 get_file_owner_and_group (psd
, buf
);
5262 get_file_owner_and_group (NULL
, buf
);
5268 no_true_file_attributes
:
5269 /* Plan B: Either getting a handle on the file failed, or the
5270 caller explicitly asked us to not bother making this
5271 information more accurate.
5273 Implementation note: In Plan B, we never bother to resolve
5274 symlinks, even if we got here because we tried Plan A and
5275 failed. That's because, even if the caller asked for extra
5276 precision by setting Vw32_get_true_file_attributes to t,
5277 resolving symlinks requires acquiring a file handle to the
5278 symlink, which we already know will fail. And if the user
5279 did not ask for extra precision, resolving symlinks will fly
5280 in the face of that request, since the user then wants the
5281 lightweight version of the code. */
5282 rootdir
= (path
>= save_name
+ len
- 1
5283 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5285 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5286 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5287 if (IS_DIRECTORY_SEP (r
[0])
5288 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5291 /* Note: If NAME is a symlink to the root of a UNC volume
5292 (i.e. "\\SERVER"), we will not detect that here, and we will
5293 return data about the symlink as result of FindFirst below.
5294 This is unfortunate, but that marginal use case does not
5295 justify a call to chase_symlinks which would impose a penalty
5296 on all the other use cases. (We get here for symlinks to
5297 roots of UNC volumes because CreateFile above fails for them,
5298 unlike with symlinks to root directories X:\ of drives.) */
5299 if (is_unc_volume (name
))
5301 fattrs
= unc_volume_file_attributes (name
);
5305 ctime
= atime
= wtime
= utc_base_ft
;
5309 /* Make sure root directories end in a slash. */
5310 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5311 strcpy (name
+ len
, "\\");
5312 if (GetDriveType (name
) < 2)
5318 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5319 ctime
= atime
= wtime
= utc_base_ft
;
5325 /* Make sure non-root directories do NOT end in a slash,
5326 otherwise FindFirstFile might fail. */
5327 if (IS_DIRECTORY_SEP (name
[len
-1]))
5330 /* (This is hacky, but helps when doing file completions on
5331 network drives.) Optimize by using information available from
5332 active readdir if possible. */
5333 len
= strlen (dir_pathname
);
5334 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5336 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5337 && last_dir_find_data
!= -1
5338 && !(is_a_symlink
&& follow_symlinks
)
5339 /* The 2 file-name comparisons below support only ASCII
5340 characters, and will lose (compare not equal) when
5341 the file names include non-ASCII characters that are
5342 the same but for the case. However, doing this
5343 properly involves: (a) converting both file names to
5344 UTF-16, (b) lower-casing both names using CharLowerW,
5345 and (c) comparing the results; this would be quite a
5346 bit slower, whereas Plan B is for users who want
5347 lightweight albeit inaccurate version of 'stat'. */
5348 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5349 && IS_DIRECTORY_SEP (name
[len
])
5350 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5352 have_wfd
= last_dir_find_data
;
5353 /* This was the last entry returned by readdir. */
5354 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5355 wfd_w
= dir_find_data_w
;
5357 wfd_a
= dir_find_data_a
;
5361 logon_network_drive (name
);
5363 if (w32_unicode_filenames
)
5365 filename_to_utf16 (name
, name_w
);
5366 fh
= FindFirstFileW (name_w
, &wfd_w
);
5367 have_wfd
= DIR_FIND_DATA_W
;
5371 filename_to_ansi (name
, name_a
);
5372 /* If NAME includes characters not representable by
5373 the current ANSI codepage, filename_to_ansi
5374 usually replaces them with a '?'. We don't want
5375 to let FindFirstFileA interpret those as wildcards,
5376 and "succeed", returning us data from some random
5377 file in the same directory. */
5378 if (_mbspbrk (name_a
, "?"))
5379 fh
= INVALID_HANDLE_VALUE
;
5381 fh
= FindFirstFileA (name_a
, &wfd_a
);
5382 have_wfd
= DIR_FIND_DATA_A
;
5384 if (fh
== INVALID_HANDLE_VALUE
)
5391 /* Note: if NAME is a symlink, the information we get from
5392 FindFirstFile is for the symlink, not its target. */
5393 if (have_wfd
== DIR_FIND_DATA_W
)
5395 fattrs
= wfd_w
.dwFileAttributes
;
5396 ctime
= wfd_w
.ftCreationTime
;
5397 atime
= wfd_w
.ftLastAccessTime
;
5398 wtime
= wfd_w
.ftLastWriteTime
;
5399 fs_high
= wfd_w
.nFileSizeHigh
;
5400 fs_low
= wfd_w
.nFileSizeLow
;
5404 fattrs
= wfd_a
.dwFileAttributes
;
5405 ctime
= wfd_a
.ftCreationTime
;
5406 atime
= wfd_a
.ftLastAccessTime
;
5407 wtime
= wfd_a
.ftLastWriteTime
;
5408 fs_high
= wfd_a
.nFileSizeHigh
;
5409 fs_low
= wfd_a
.nFileSizeLow
;
5413 serialnum
= volume_info
.serialnum
;
5415 if (is_a_symlink
&& !follow_symlinks
)
5416 buf
->st_mode
= S_IFLNK
;
5417 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5418 buf
->st_mode
= S_IFDIR
;
5420 buf
->st_mode
= S_IFREG
;
5422 get_file_owner_and_group (NULL
, buf
);
5425 buf
->st_ino
= fake_inode
;
5427 buf
->st_dev
= serialnum
;
5428 buf
->st_rdev
= serialnum
;
5430 buf
->st_size
= fs_high
;
5431 buf
->st_size
<<= 32;
5432 buf
->st_size
+= fs_low
;
5433 buf
->st_nlink
= nlinks
;
5435 /* Convert timestamps to Unix format. */
5436 buf
->st_mtime
= convert_time (wtime
);
5437 buf
->st_atime
= convert_time (atime
);
5438 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5439 buf
->st_ctime
= convert_time (ctime
);
5440 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5442 /* determine rwx permissions */
5443 if (is_a_symlink
&& !follow_symlinks
)
5444 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5447 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5448 permission
= S_IREAD
;
5450 permission
= S_IREAD
| S_IWRITE
;
5452 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5453 permission
|= S_IEXEC
;
5454 else if (is_exec (name
))
5455 permission
|= S_IEXEC
;
5458 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5464 stat (const char * path
, struct stat
* buf
)
5466 return stat_worker (path
, buf
, 1);
5470 lstat (const char * path
, struct stat
* buf
)
5472 return stat_worker (path
, buf
, 0);
5476 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5478 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5479 This is good enough for the current usage in Emacs, but is fragile.
5481 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5482 Gnulib does this and can serve as a model. */
5483 char fullname
[MAX_UTF8_PATH
];
5487 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5489 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5490 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5493 errno
= ENAMETOOLONG
;
5499 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5502 /* Provide fstat and utime as well as stat for consistent handling of
5505 fstat (int desc
, struct stat
* buf
)
5507 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5508 BY_HANDLE_FILE_INFORMATION info
;
5509 unsigned __int64 fake_inode
;
5512 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5514 case FILE_TYPE_DISK
:
5515 buf
->st_mode
= S_IFREG
;
5516 if (!GetFileInformationByHandle (fh
, &info
))
5522 case FILE_TYPE_PIPE
:
5523 buf
->st_mode
= S_IFIFO
;
5525 case FILE_TYPE_CHAR
:
5526 case FILE_TYPE_UNKNOWN
:
5528 buf
->st_mode
= S_IFCHR
;
5530 memset (&info
, 0, sizeof (info
));
5531 info
.dwFileAttributes
= 0;
5532 info
.ftCreationTime
= utc_base_ft
;
5533 info
.ftLastAccessTime
= utc_base_ft
;
5534 info
.ftLastWriteTime
= utc_base_ft
;
5537 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5538 buf
->st_mode
= S_IFDIR
;
5540 buf
->st_nlink
= info
.nNumberOfLinks
;
5541 /* Might as well use file index to fake inode values, but this
5542 is not guaranteed to be unique unless we keep a handle open
5543 all the time (even then there are situations where it is
5544 not unique). Reputedly, there are at most 48 bits of info
5545 (on NTFS, presumably less on FAT). */
5546 fake_inode
= info
.nFileIndexHigh
;
5548 fake_inode
+= info
.nFileIndexLow
;
5550 /* MSVC defines _ino_t to be short; other libc's might not. */
5551 if (sizeof (buf
->st_ino
) == 2)
5552 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5554 buf
->st_ino
= fake_inode
;
5556 /* If the caller so requested, get the true file owner and group.
5557 Otherwise, consider the file to belong to the current user. */
5558 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5559 get_file_owner_and_group (NULL
, buf
);
5562 PSECURITY_DESCRIPTOR psd
= NULL
;
5564 psd
= get_file_security_desc_by_handle (fh
);
5567 get_file_owner_and_group (psd
, buf
);
5571 get_file_owner_and_group (NULL
, buf
);
5574 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5575 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5577 buf
->st_size
= info
.nFileSizeHigh
;
5578 buf
->st_size
<<= 32;
5579 buf
->st_size
+= info
.nFileSizeLow
;
5581 /* Convert timestamps to Unix format. */
5582 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5583 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5584 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5585 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5586 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5588 /* determine rwx permissions */
5589 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5590 permission
= S_IREAD
;
5592 permission
= S_IREAD
| S_IWRITE
;
5594 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5595 permission
|= S_IEXEC
;
5598 #if 0 /* no way of knowing the filename */
5599 char * p
= strrchr (name
, '.');
5601 (xstrcasecmp (p
, ".exe") == 0 ||
5602 xstrcasecmp (p
, ".com") == 0 ||
5603 xstrcasecmp (p
, ".bat") == 0 ||
5604 xstrcasecmp (p
, ".cmd") == 0))
5605 permission
|= S_IEXEC
;
5609 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5614 /* A version of 'utime' which handles directories as well as
5618 utime (const char *name
, struct utimbuf
*times
)
5620 struct utimbuf deftime
;
5627 deftime
.modtime
= deftime
.actime
= time (NULL
);
5631 if (w32_unicode_filenames
)
5633 wchar_t name_utf16
[MAX_PATH
];
5635 if (filename_to_utf16 (name
, name_utf16
) != 0)
5636 return -1; /* errno set by filename_to_utf16 */
5638 /* Need write access to set times. */
5639 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5640 /* If NAME specifies a directory, FILE_SHARE_DELETE
5641 allows other processes to delete files inside it,
5642 while we have the directory open. */
5643 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5644 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5648 char name_ansi
[MAX_PATH
];
5650 if (filename_to_ansi (name
, name_ansi
) != 0)
5651 return -1; /* errno set by filename_to_ansi */
5653 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5654 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5655 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5657 if (fh
!= INVALID_HANDLE_VALUE
)
5659 convert_from_time_t (times
->actime
, &atime
);
5660 convert_from_time_t (times
->modtime
, &mtime
);
5661 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5671 DWORD err
= GetLastError ();
5675 case ERROR_FILE_NOT_FOUND
:
5676 case ERROR_PATH_NOT_FOUND
:
5677 case ERROR_INVALID_DRIVE
:
5678 case ERROR_BAD_NETPATH
:
5679 case ERROR_DEV_NOT_EXIST
:
5680 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5681 file name includes ?s, i.e. translation to ANSI failed. */
5682 case ERROR_INVALID_NAME
:
5685 case ERROR_TOO_MANY_OPEN_FILES
:
5688 case ERROR_ACCESS_DENIED
:
5689 case ERROR_SHARING_VIOLATION
:
5702 sys_umask (int mode
)
5704 static int current_mask
;
5705 int retval
, arg
= 0;
5707 /* The only bit we really support is the write bit. Files are
5708 always readable on MS-Windows, and the execute bit does not exist
5710 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5711 to prevent access by other users on NTFS. */
5712 if ((mode
& S_IWRITE
) != 0)
5715 retval
= _umask (arg
);
5716 /* Merge into the return value the bits they've set the last time,
5717 which msvcrt.dll ignores and never returns. Emacs insists on its
5718 notion of mask being identical to what we return. */
5719 retval
|= (current_mask
& ~S_IWRITE
);
5720 current_mask
= mode
;
5726 /* Symlink-related functions. */
5727 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5728 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5732 symlink (char const *filename
, char const *linkname
)
5734 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5736 int dir_access
, filename_ends_in_slash
;
5738 /* Diagnostics follows Posix as much as possible. */
5739 if (filename
== NULL
|| linkname
== NULL
)
5749 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5751 errno
= ENAMETOOLONG
;
5755 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5756 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5762 /* Note: since empty FILENAME was already rejected, we can safely
5763 refer to FILENAME[1]. */
5764 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5766 /* Non-absolute FILENAME is understood as being relative to
5767 LINKNAME's directory. We need to prepend that directory to
5768 FILENAME to get correct results from faccessat below, since
5769 otherwise it will interpret FILENAME relative to the
5770 directory where the Emacs process runs. Note that
5771 make-symbolic-link always makes sure LINKNAME is a fully
5772 expanded file name. */
5773 char tem
[MAX_UTF8_PATH
];
5774 char *p
= linkfn
+ strlen (linkfn
);
5776 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5779 strncpy (tem
, linkfn
, p
- linkfn
);
5780 strcpy (tem
+ (p
- linkfn
), filename
);
5781 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5784 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5786 /* Since Windows distinguishes between symlinks to directories and
5787 to files, we provide a kludgy feature: if FILENAME doesn't
5788 exist, but ends in a slash, we create a symlink to directory. If
5789 FILENAME exists and is a directory, we always create a symlink to
5791 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5792 if (dir_access
== 0 || filename_ends_in_slash
)
5793 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5795 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5796 if (filename_ends_in_slash
)
5797 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5800 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5802 /* ENOSYS is set by create_symbolic_link, when it detects that
5803 the OS doesn't support the CreateSymbolicLink API. */
5804 if (errno
!= ENOSYS
)
5806 DWORD w32err
= GetLastError ();
5810 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5811 TGTFN point to the same file name, go figure. */
5813 case ERROR_FILE_EXISTS
:
5816 case ERROR_ACCESS_DENIED
:
5819 case ERROR_FILE_NOT_FOUND
:
5820 case ERROR_PATH_NOT_FOUND
:
5821 case ERROR_BAD_NETPATH
:
5822 case ERROR_INVALID_REPARSE_DATA
:
5825 case ERROR_DIRECTORY
:
5828 case ERROR_PRIVILEGE_NOT_HELD
:
5829 case ERROR_NOT_ALL_ASSIGNED
:
5832 case ERROR_DISK_FULL
:
5845 /* A quick inexpensive test of whether FILENAME identifies a file that
5846 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5847 must already be in the normalized form returned by
5848 map_w32_filename. If the symlink is to a directory, the
5849 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5851 Note: for repeated operations on many files, it is best to test
5852 whether the underlying volume actually supports symlinks, by
5853 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5854 avoid the call to this function if it doesn't. That's because the
5855 call to GetFileAttributes takes a non-negligible time, especially
5856 on non-local or removable filesystems. See stat_worker for an
5857 example of how to do that. */
5859 is_symlink (const char *filename
)
5862 wchar_t filename_w
[MAX_PATH
];
5863 char filename_a
[MAX_PATH
];
5864 WIN32_FIND_DATAW wfdw
;
5865 WIN32_FIND_DATAA wfda
;
5867 int attrs_mean_symlink
;
5869 if (w32_unicode_filenames
)
5871 filename_to_utf16 (filename
, filename_w
);
5872 attrs
= GetFileAttributesW (filename_w
);
5876 filename_to_ansi (filename
, filename_a
);
5877 attrs
= GetFileAttributesA (filename_a
);
5881 DWORD w32err
= GetLastError ();
5885 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5887 case ERROR_ACCESS_DENIED
:
5890 case ERROR_FILE_NOT_FOUND
:
5891 case ERROR_PATH_NOT_FOUND
:
5898 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5900 logon_network_drive (filename
);
5901 if (w32_unicode_filenames
)
5903 fh
= FindFirstFileW (filename_w
, &wfdw
);
5904 attrs_mean_symlink
=
5905 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5906 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5907 if (attrs_mean_symlink
)
5908 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5910 else if (_mbspbrk (filename_a
, "?"))
5912 /* filename_to_ansi failed to convert the file name. */
5918 fh
= FindFirstFileA (filename_a
, &wfda
);
5919 attrs_mean_symlink
=
5920 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5921 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5922 if (attrs_mean_symlink
)
5923 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5925 if (fh
== INVALID_HANDLE_VALUE
)
5928 return attrs_mean_symlink
;
5931 /* If NAME identifies a symbolic link, copy into BUF the file name of
5932 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5933 null-terminate the target name, even if it fits. Return the number
5934 of bytes copied, or -1 if NAME is not a symlink or any error was
5935 encountered while resolving it. The file name copied into BUF is
5936 encoded in the current ANSI codepage. */
5938 readlink (const char *name
, char *buf
, size_t buf_size
)
5941 TOKEN_PRIVILEGES privs
;
5942 int restore_privs
= 0;
5945 char resolved
[MAX_UTF8_PATH
];
5958 path
= map_w32_filename (name
, NULL
);
5960 if (strlen (path
) > MAX_UTF8_PATH
)
5962 errno
= ENAMETOOLONG
;
5967 if (is_windows_9x () == TRUE
5968 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5969 || !is_symlink (path
))
5972 errno
= EINVAL
; /* not a symlink */
5976 /* Done with simple tests, now we're in for some _real_ work. */
5977 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5979 /* Implementation note: From here and onward, don't return early,
5980 since that will fail to restore the original set of privileges of
5981 the calling thread. */
5983 retval
= -1; /* not too optimistic, are we? */
5985 /* Note: In the next call to CreateFile, we use zero as the 2nd
5986 argument because, when the symlink is a hidden/system file,
5987 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5988 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5989 and directory symlinks. */
5990 if (w32_unicode_filenames
)
5992 wchar_t path_w
[MAX_PATH
];
5994 filename_to_utf16 (path
, path_w
);
5995 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5996 FILE_FLAG_OPEN_REPARSE_POINT
5997 | FILE_FLAG_BACKUP_SEMANTICS
,
6002 char path_a
[MAX_PATH
];
6004 filename_to_ansi (path
, path_a
);
6005 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
6006 FILE_FLAG_OPEN_REPARSE_POINT
6007 | FILE_FLAG_BACKUP_SEMANTICS
,
6010 if (sh
!= INVALID_HANDLE_VALUE
)
6012 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
6013 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
6016 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
6017 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
6020 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
6024 /* Copy the link target name, in wide characters, from
6025 reparse_data, then convert it to multibyte encoding in
6026 the current locale's codepage. */
6030 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
6032 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
6033 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
6034 size_t size_to_copy
= buf_size
;
6036 /* According to MSDN, PrintNameLength does not include the
6037 terminating null character. */
6038 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
6039 memcpy (lwname
, lwname_src
, lwname_len
);
6040 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
6041 filename_from_utf16 (lwname
, resolved
);
6042 dostounix_filename (resolved
);
6043 lname_size
= strlen (resolved
) + 1;
6044 if (lname_size
<= buf_size
)
6045 size_to_copy
= lname_size
;
6046 strncpy (buf
, resolved
, size_to_copy
);
6048 retval
= size_to_copy
;
6054 /* CreateFile failed. */
6055 DWORD w32err2
= GetLastError ();
6059 case ERROR_FILE_NOT_FOUND
:
6060 case ERROR_PATH_NOT_FOUND
:
6063 case ERROR_ACCESS_DENIED
:
6064 case ERROR_TOO_MANY_OPEN_FILES
:
6074 restore_privilege (&privs
);
6082 readlinkat (int fd
, char const *name
, char *buffer
,
6085 /* Rely on a hack: an open directory is modeled as file descriptor 0,
6086 as in fstatat. FIXME: Add proper support for readlinkat. */
6087 char fullname
[MAX_UTF8_PATH
];
6091 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
6094 errno
= ENAMETOOLONG
;
6100 return readlink (name
, buffer
, buffer_size
);
6103 /* If FILE is a symlink, return its target (stored in a static
6104 buffer); otherwise return FILE.
6106 This function repeatedly resolves symlinks in the last component of
6107 a chain of symlink file names, as in foo -> bar -> baz -> ...,
6108 until it arrives at a file whose last component is not a symlink,
6109 or some error occurs. It returns the target of the last
6110 successfully resolved symlink in the chain. If it succeeds to
6111 resolve even a single symlink, the value returned is an absolute
6112 file name with backslashes (result of GetFullPathName). By
6113 contrast, if the original FILE is returned, it is unaltered.
6115 Note: This function can set errno even if it succeeds.
6117 Implementation note: we only resolve the last portion ("basename")
6118 of the argument FILE and of each following file in the chain,
6119 disregarding any possible symlinks in its leading directories.
6120 This is because Windows system calls and library functions
6121 transparently resolve symlinks in leading directories and return
6122 correct information, as long as the basename is not a symlink. */
6124 chase_symlinks (const char *file
)
6126 static char target
[MAX_UTF8_PATH
];
6127 char link
[MAX_UTF8_PATH
];
6128 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
6129 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
6130 ssize_t res
, link_len
;
6133 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
6134 return (char *)file
;
6136 if (w32_unicode_filenames
)
6138 wchar_t file_w
[MAX_PATH
];
6140 filename_to_utf16 (file
, file_w
);
6141 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
6142 return (char *)file
;
6143 filename_from_utf16 (link_w
, link
);
6147 char file_a
[MAX_PATH
];
6149 filename_to_ansi (file
, file_a
);
6150 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
6151 return (char *)file
;
6152 filename_from_ansi (link_a
, link
);
6154 link_len
= strlen (link
);
6159 /* Remove trailing slashes, as we want to resolve the last
6160 non-trivial part of the link name. */
6161 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
6162 link
[link_len
--] = '\0';
6164 res
= readlink (link
, target
, MAX_UTF8_PATH
);
6168 if (!(IS_DEVICE_SEP (target
[1])
6169 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
6171 /* Target is relative. Append it to the directory part of
6172 the symlink, then copy the result back to target. */
6173 char *p
= link
+ link_len
;
6175 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
6178 strcpy (target
, link
);
6180 /* Resolve any "." and ".." to get a fully-qualified file name
6182 if (w32_unicode_filenames
)
6184 filename_to_utf16 (target
, target_w
);
6185 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
6187 filename_from_utf16 (link_w
, link
);
6191 filename_to_ansi (target
, target_a
);
6192 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
6194 filename_from_ansi (link_a
, link
);
6196 link_len
= strlen (link
);
6198 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6200 if (loop_count
> 100)
6203 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6204 return (char *)file
;
6209 /* Posix ACL emulation. */
6212 acl_valid (acl_t acl
)
6214 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6218 acl_to_text (acl_t acl
, ssize_t
*size
)
6221 SECURITY_INFORMATION flags
=
6222 OWNER_SECURITY_INFORMATION
|
6223 GROUP_SECURITY_INFORMATION
|
6224 DACL_SECURITY_INFORMATION
;
6225 char *retval
= NULL
;
6231 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6234 /* We don't want to mix heaps, so we duplicate the string in our
6235 heap and free the one allocated by the API. */
6236 retval
= xstrdup (str_acl
);
6239 LocalFree (str_acl
);
6241 else if (errno
!= ENOTSUP
)
6248 acl_from_text (const char *acl_str
)
6250 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6256 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6259 retval
= xmalloc (sd_size
);
6260 memcpy (retval
, psd
, sd_size
);
6263 else if (errno
!= ENOTSUP
)
6270 acl_free (void *ptr
)
6277 acl_get_file (const char *fname
, acl_type_t type
)
6279 PSECURITY_DESCRIPTOR psd
= NULL
;
6280 const char *filename
;
6282 if (type
== ACL_TYPE_ACCESS
)
6285 SECURITY_INFORMATION si
=
6286 OWNER_SECURITY_INFORMATION
|
6287 GROUP_SECURITY_INFORMATION
|
6288 DACL_SECURITY_INFORMATION
;
6291 filename
= map_w32_filename (fname
, NULL
);
6292 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6293 fname
= chase_symlinks (filename
);
6298 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6299 && errno
!= ENOTSUP
)
6301 err
= GetLastError ();
6302 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6304 psd
= xmalloc (sd_len
);
6305 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6312 else if (err
== ERROR_FILE_NOT_FOUND
6313 || err
== ERROR_PATH_NOT_FOUND
6314 /* ERROR_INVALID_NAME is what we get if
6315 w32-unicode-filenames is nil and the file cannot
6316 be encoded in the current ANSI codepage. */
6317 || err
== ERROR_INVALID_NAME
)
6325 else if (type
!= ACL_TYPE_DEFAULT
)
6332 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6334 TOKEN_PRIVILEGES old1
, old2
;
6336 int st
= 0, retval
= -1;
6337 SECURITY_INFORMATION flags
= 0;
6338 PSID psidOwner
, psidGroup
;
6343 const char *filename
;
6345 if (acl_valid (acl
) != 0
6346 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6352 if (type
== ACL_TYPE_DEFAULT
)
6358 filename
= map_w32_filename (fname
, NULL
);
6359 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6360 fname
= chase_symlinks (filename
);
6364 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6367 flags
|= OWNER_SECURITY_INFORMATION
;
6368 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6371 flags
|= GROUP_SECURITY_INFORMATION
;
6372 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6375 flags
|= DACL_SECURITY_INFORMATION
;
6379 /* According to KB-245153, setting the owner will succeed if either:
6380 (1) the caller is the user who will be the new owner, and has the
6381 SE_TAKE_OWNERSHIP privilege, or
6382 (2) the caller has the SE_RESTORE privilege, in which case she can
6383 set any valid user or group as the owner
6385 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6386 privileges, and disregard any failures in obtaining them. If
6387 these privileges cannot be obtained, and do not already exist in
6388 the calling thread's security token, this function could fail
6390 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6392 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6397 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6398 DACL inheritance is involved, but it seems to preserve ownership
6399 better than SetNamedSecurityInfo, which is important e.g., in
6401 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6403 err
= GetLastError ();
6405 if (errno
!= ENOTSUP
)
6406 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6407 psidOwner
, psidGroup
, pacl
, NULL
);
6410 err
= ERROR_SUCCESS
;
6411 if (err
!= ERROR_SUCCESS
)
6413 if (errno
== ENOTSUP
)
6415 else if (err
== ERROR_INVALID_OWNER
6416 || err
== ERROR_NOT_ALL_ASSIGNED
6417 || err
== ERROR_ACCESS_DENIED
)
6419 /* Maybe the requested ACL and the one the file already has
6420 are identical, in which case we can silently ignore the
6421 failure. (And no, Windows doesn't.) */
6422 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6427 char *acl_from
= acl_to_text (current_acl
, NULL
);
6428 char *acl_to
= acl_to_text (acl
, NULL
);
6430 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6436 acl_free (acl_from
);
6439 acl_free (current_acl
);
6442 else if (err
== ERROR_FILE_NOT_FOUND
6443 || err
== ERROR_PATH_NOT_FOUND
6444 /* ERROR_INVALID_NAME is what we get if
6445 w32-unicode-filenames is nil and the file cannot be
6446 encoded in the current ANSI codepage. */
6447 || err
== ERROR_INVALID_NAME
)
6461 restore_privilege (&old2
);
6462 restore_privilege (&old1
);
6469 /* Return true if errno value ERRNUM indicates that ACLs are well
6470 supported on this system. ERRNUM should be an errno value obtained
6471 after an ACL-related system call fails. */
6473 acl_errno_valid (int errnum
)
6487 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6488 have a fixed max size for file names, so we don't need the kind of
6489 alloc/malloc/realloc dance the gnulib version does. We also don't
6490 support FD-relative symlinks. */
6492 careadlinkat (int fd
, char const *filename
,
6493 char *buffer
, size_t buffer_size
,
6494 struct allocator
const *alloc
,
6495 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6497 char linkname
[MAX_UTF8_PATH
];
6500 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6504 char *retval
= buffer
;
6506 linkname
[link_size
++] = '\0';
6507 if (link_size
> buffer_size
)
6508 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6510 memcpy (retval
, linkname
, link_size
);
6518 w32_copy_file (const char *from
, const char *to
,
6519 int keep_time
, int preserve_ownership
, int copy_acls
)
6523 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6524 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6526 /* We ignore preserve_ownership for now. */
6527 preserve_ownership
= preserve_ownership
;
6531 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6532 if (acl
== NULL
&& acl_errno_valid (errno
))
6535 if (w32_unicode_filenames
)
6537 filename_to_utf16 (from
, from_w
);
6538 filename_to_utf16 (to
, to_w
);
6539 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6543 filename_to_ansi (from
, from_a
);
6544 filename_to_ansi (to
, to_a
);
6545 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6549 /* CopyFile doesn't set errno when it fails. By far the most
6550 "popular" reason is that the target is read-only. */
6551 DWORD err
= GetLastError ();
6555 case ERROR_FILE_NOT_FOUND
:
6558 case ERROR_ACCESS_DENIED
:
6561 case ERROR_ENCRYPTION_FAILED
:
6573 /* CopyFile retains the timestamp by default. However, see
6574 "Community Additions" for CopyFile: it sounds like that is not
6575 entirely true. Testing on Windows XP confirms that modified time
6576 is copied, but creation and last-access times are not.
6578 else if (!keep_time
)
6580 struct timespec now
;
6583 if (w32_unicode_filenames
)
6585 /* Ensure file is writable while its times are set. */
6586 attributes
= GetFileAttributesW (to_w
);
6587 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6588 now
= current_timespec ();
6589 if (set_file_times (-1, to
, now
, now
))
6591 /* Restore original attributes. */
6592 SetFileAttributesW (to_w
, attributes
);
6597 /* Restore original attributes. */
6598 SetFileAttributesW (to_w
, attributes
);
6602 attributes
= GetFileAttributesA (to_a
);
6603 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6604 now
= current_timespec ();
6605 if (set_file_times (-1, to
, now
, now
))
6607 SetFileAttributesA (to_a
, attributes
);
6612 SetFileAttributesA (to_a
, attributes
);
6618 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6620 if (fail
&& acl_errno_valid (errno
))
6628 /* Support for browsing other processes and their attributes. See
6629 process.c for the Lisp bindings. */
6631 /* Helper wrapper functions. */
6633 static HANDLE WINAPI
6634 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6636 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6638 if (g_b_init_create_toolhelp32_snapshot
== 0)
6640 g_b_init_create_toolhelp32_snapshot
= 1;
6641 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6642 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6643 "CreateToolhelp32Snapshot");
6645 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6647 return INVALID_HANDLE_VALUE
;
6649 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6653 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6655 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6657 if (g_b_init_process32_first
== 0)
6659 g_b_init_process32_first
= 1;
6660 s_pfn_Process32_First
= (Process32First_Proc
)
6661 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6664 if (s_pfn_Process32_First
== NULL
)
6668 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6672 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6674 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6676 if (g_b_init_process32_next
== 0)
6678 g_b_init_process32_next
= 1;
6679 s_pfn_Process32_Next
= (Process32Next_Proc
)
6680 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6683 if (s_pfn_Process32_Next
== NULL
)
6687 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6691 open_thread_token (HANDLE ThreadHandle
,
6692 DWORD DesiredAccess
,
6694 PHANDLE TokenHandle
)
6696 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6697 HMODULE hm_advapi32
= NULL
;
6698 if (is_windows_9x () == TRUE
)
6700 SetLastError (ERROR_NOT_SUPPORTED
);
6703 if (g_b_init_open_thread_token
== 0)
6705 g_b_init_open_thread_token
= 1;
6706 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6707 s_pfn_Open_Thread_Token
=
6708 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6710 if (s_pfn_Open_Thread_Token
== NULL
)
6712 SetLastError (ERROR_NOT_SUPPORTED
);
6716 s_pfn_Open_Thread_Token (
6725 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6727 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6728 HMODULE hm_advapi32
= NULL
;
6729 if (is_windows_9x () == TRUE
)
6733 if (g_b_init_impersonate_self
== 0)
6735 g_b_init_impersonate_self
= 1;
6736 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6737 s_pfn_Impersonate_Self
=
6738 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6740 if (s_pfn_Impersonate_Self
== NULL
)
6744 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6748 revert_to_self (void)
6750 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6751 HMODULE hm_advapi32
= NULL
;
6752 if (is_windows_9x () == TRUE
)
6756 if (g_b_init_revert_to_self
== 0)
6758 g_b_init_revert_to_self
= 1;
6759 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6760 s_pfn_Revert_To_Self
=
6761 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6763 if (s_pfn_Revert_To_Self
== NULL
)
6767 return s_pfn_Revert_To_Self ();
6771 get_process_memory_info (HANDLE h_proc
,
6772 PPROCESS_MEMORY_COUNTERS mem_counters
,
6775 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6776 HMODULE hm_psapi
= NULL
;
6777 if (is_windows_9x () == TRUE
)
6781 if (g_b_init_get_process_memory_info
== 0)
6783 g_b_init_get_process_memory_info
= 1;
6784 hm_psapi
= LoadLibrary ("Psapi.dll");
6786 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6787 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6789 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6793 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6797 get_process_working_set_size (HANDLE h_proc
,
6801 static GetProcessWorkingSetSize_Proc
6802 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6804 if (is_windows_9x () == TRUE
)
6808 if (g_b_init_get_process_working_set_size
== 0)
6810 g_b_init_get_process_working_set_size
= 1;
6811 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6812 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6813 "GetProcessWorkingSetSize");
6815 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6819 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6823 global_memory_status (MEMORYSTATUS
*buf
)
6825 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6827 if (is_windows_9x () == TRUE
)
6831 if (g_b_init_global_memory_status
== 0)
6833 g_b_init_global_memory_status
= 1;
6834 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6835 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6836 "GlobalMemoryStatus");
6838 if (s_pfn_Global_Memory_Status
== NULL
)
6842 return s_pfn_Global_Memory_Status (buf
);
6846 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6848 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6850 if (is_windows_9x () == TRUE
)
6854 if (g_b_init_global_memory_status_ex
== 0)
6856 g_b_init_global_memory_status_ex
= 1;
6857 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6858 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6859 "GlobalMemoryStatusEx");
6861 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6865 return s_pfn_Global_Memory_Status_Ex (buf
);
6869 list_system_processes (void)
6871 Lisp_Object proclist
= Qnil
;
6874 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6876 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6878 PROCESSENTRY32 proc_entry
;
6882 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6883 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6884 res
= process32_next (h_snapshot
, &proc_entry
))
6886 proc_id
= proc_entry
.th32ProcessID
;
6887 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6890 CloseHandle (h_snapshot
);
6891 proclist
= Fnreverse (proclist
);
6898 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6900 TOKEN_PRIVILEGES priv
;
6901 DWORD priv_size
= sizeof (priv
);
6902 DWORD opriv_size
= sizeof (*old_priv
);
6903 HANDLE h_token
= NULL
;
6904 HANDLE h_thread
= GetCurrentThread ();
6908 res
= open_thread_token (h_thread
,
6909 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6911 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6913 if (impersonate_self (SecurityImpersonation
))
6914 res
= open_thread_token (h_thread
,
6915 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6920 priv
.PrivilegeCount
= 1;
6921 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6922 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6923 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6924 old_priv
, &opriv_size
)
6925 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6929 CloseHandle (h_token
);
6935 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6937 DWORD priv_size
= sizeof (*priv
);
6938 HANDLE h_token
= NULL
;
6941 if (open_thread_token (GetCurrentThread (),
6942 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6945 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6946 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6950 CloseHandle (h_token
);
6956 ltime (ULONGLONG time_100ns
)
6958 ULONGLONG time_sec
= time_100ns
/ 10000000;
6959 int subsec
= time_100ns
% 10000000;
6960 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6961 subsec
/ 10, subsec
% 10 * 100000);
6964 #define U64_TO_LISP_TIME(time) ltime (time)
6967 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6968 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6971 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6972 ULONGLONG tem1
, tem2
, tem3
, tem
;
6975 || !get_process_times_fn
6976 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6977 &ft_kernel
, &ft_user
))
6980 GetSystemTimeAsFileTime (&ft_current
);
6982 FILETIME_TO_U64 (tem1
, ft_kernel
);
6983 *stime
= U64_TO_LISP_TIME (tem1
);
6985 FILETIME_TO_U64 (tem2
, ft_user
);
6986 *utime
= U64_TO_LISP_TIME (tem2
);
6989 *ttime
= U64_TO_LISP_TIME (tem3
);
6991 FILETIME_TO_U64 (tem
, ft_creation
);
6992 /* Process no 4 (System) returns zero creation time. */
6995 *ctime
= U64_TO_LISP_TIME (tem
);
6999 FILETIME_TO_U64 (tem3
, ft_current
);
7000 tem
= (tem3
- utc_base
) - tem
;
7002 *etime
= U64_TO_LISP_TIME (tem
);
7006 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
7017 system_process_attributes (Lisp_Object pid
)
7019 Lisp_Object attrs
= Qnil
;
7020 Lisp_Object cmd_str
, decoded_cmd
, tem
;
7021 HANDLE h_snapshot
, h_proc
;
7024 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
7025 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
7026 DWORD glength
= sizeof (gname
);
7027 HANDLE token
= NULL
;
7028 SID_NAME_USE user_type
;
7029 unsigned char *buf
= NULL
;
7031 TOKEN_USER user_token
;
7032 TOKEN_PRIMARY_GROUP group_token
;
7035 PROCESS_MEMORY_COUNTERS mem
;
7036 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
7037 SIZE_T minrss
, maxrss
;
7039 MEMORY_STATUS_EX memstex
;
7040 double totphys
= 0.0;
7041 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
7043 BOOL result
= FALSE
;
7045 CHECK_NUMBER_OR_FLOAT (pid
);
7046 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
7048 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
7050 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
7055 pe
.dwSize
= sizeof (PROCESSENTRY32
);
7056 for (res
= process32_first (h_snapshot
, &pe
); res
;
7057 res
= process32_next (h_snapshot
, &pe
))
7059 if (proc_id
== pe
.th32ProcessID
)
7062 decoded_cmd
= build_string ("Idle");
7065 /* Decode the command name from locale-specific
7067 cmd_str
= build_unibyte_string (pe
.szExeFile
);
7070 code_convert_string_norecord (cmd_str
,
7071 Vlocale_coding_system
, 0);
7073 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
7074 attrs
= Fcons (Fcons (Qppid
,
7075 make_fixnum_or_float (pe
.th32ParentProcessID
)),
7077 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
7079 attrs
= Fcons (Fcons (Qthcount
,
7080 make_fixnum_or_float (pe
.cntThreads
)),
7087 CloseHandle (h_snapshot
);
7093 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7095 /* If we were denied a handle to the process, try again after
7096 enabling the SeDebugPrivilege in our process. */
7099 TOKEN_PRIVILEGES priv_current
;
7101 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
7103 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
7105 restore_privilege (&priv_current
);
7111 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
7114 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
7115 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7117 buf
= xmalloc (blen
);
7118 result
= get_token_information (token
, TokenUser
,
7119 (LPVOID
)buf
, blen
, &needed
);
7122 memcpy (&user_token
, buf
, sizeof (user_token
));
7123 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
7125 euid
= get_rid (user_token
.User
.Sid
);
7126 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
7131 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
7134 strcpy (uname
, "unknown");
7138 ulength
= strlen (uname
);
7144 /* Determine a reasonable euid and gid values. */
7145 if (xstrcasecmp ("administrator", uname
) == 0)
7147 euid
= 500; /* well-known Administrator uid */
7148 egid
= 513; /* well-known None gid */
7152 /* Get group id and name. */
7153 result
= get_token_information (token
, TokenPrimaryGroup
,
7154 (LPVOID
)buf
, blen
, &needed
);
7155 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
7157 buf
= xrealloc (buf
, blen
= needed
);
7158 result
= get_token_information (token
, TokenPrimaryGroup
,
7159 (LPVOID
)buf
, blen
, &needed
);
7163 memcpy (&group_token
, buf
, sizeof (group_token
));
7164 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
7166 egid
= get_rid (group_token
.PrimaryGroup
);
7167 dlength
= sizeof (domain
);
7169 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
7170 gname
, &glength
, NULL
, &dlength
,
7173 w32_add_to_cache (group_token
.PrimaryGroup
,
7177 strcpy (gname
, "None");
7181 glength
= strlen (gname
);
7189 if (!is_windows_9x ())
7191 /* We couldn't open the process token, presumably because of
7192 insufficient access rights. Assume this process is run
7194 strcpy (uname
, "SYSTEM");
7195 strcpy (gname
, "None");
7196 euid
= 18; /* SYSTEM */
7197 egid
= 513; /* None */
7198 glength
= strlen (gname
);
7199 ulength
= strlen (uname
);
7201 /* If we are running under Windows 9X, where security calls are
7202 not supported, we assume all processes are run by the current
7204 else if (GetUserName (uname
, &ulength
))
7206 if (xstrcasecmp ("administrator", uname
) == 0)
7211 strcpy (gname
, "None");
7212 glength
= strlen (gname
);
7213 ulength
= strlen (uname
);
7219 strcpy (uname
, "administrator");
7220 ulength
= strlen (uname
);
7221 strcpy (gname
, "None");
7222 glength
= strlen (gname
);
7225 CloseHandle (token
);
7228 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7229 tem
= make_unibyte_string (uname
, ulength
);
7230 attrs
= Fcons (Fcons (Quser
,
7231 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7233 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7234 tem
= make_unibyte_string (gname
, glength
);
7235 attrs
= Fcons (Fcons (Qgroup
,
7236 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7239 if (global_memory_status_ex (&memstex
))
7240 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7241 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7243 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7244 double, so we need to do this for it... */
7246 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7247 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7248 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7250 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7252 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7253 else if (global_memory_status (&memst
))
7254 totphys
= memst
.dwTotalPhys
/ 1024.0;
7257 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7260 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7262 attrs
= Fcons (Fcons (Qmajflt
,
7263 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7265 attrs
= Fcons (Fcons (Qvsize
,
7266 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7268 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7270 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7273 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7275 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7277 attrs
= Fcons (Fcons (Qmajflt
,
7278 make_fixnum_or_float (mem
.PageFaultCount
)),
7280 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7282 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7285 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7287 DWORD rss
= maxrss
/ 1024;
7289 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7291 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7294 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7296 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7297 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7298 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7299 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7300 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7301 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7304 /* FIXME: Retrieve command line by walking the PEB of the process. */
7307 CloseHandle (h_proc
);
7312 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7313 unsigned long long *totalswap
, unsigned long long *freeswap
)
7316 MEMORY_STATUS_EX memstex
;
7318 /* Use GlobalMemoryStatusEx if available, as it can report more than
7320 if (global_memory_status_ex (&memstex
))
7322 *totalram
= memstex
.ullTotalPhys
;
7323 *freeram
= memstex
.ullAvailPhys
;
7324 *totalswap
= memstex
.ullTotalPageFile
;
7325 *freeswap
= memstex
.ullAvailPageFile
;
7328 else if (global_memory_status (&memst
))
7330 *totalram
= memst
.dwTotalPhys
;
7331 *freeram
= memst
.dwAvailPhys
;
7332 *totalswap
= memst
.dwTotalPageFile
;
7333 *freeswap
= memst
.dwAvailPageFile
;
7341 /* Wrappers for winsock functions to map between our file descriptors
7342 and winsock's handles; also set h_errno for convenience.
7344 To allow Emacs to run on systems which don't have winsock support
7345 installed, we dynamically link to winsock on startup if present, and
7346 otherwise provide the minimum necessary functionality
7347 (eg. gethostname). */
7349 /* function pointers for relevant socket functions */
7350 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7351 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7352 int (PASCAL
*pfn_WSAGetLastError
) (void);
7353 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7354 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7355 WSANETWORKEVENTS
*NetworkEvents
);
7357 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7358 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7359 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7360 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7361 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7362 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7363 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7364 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7365 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7366 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7367 int (PASCAL
*pfn_WSACleanup
) (void);
7369 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7370 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7371 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7372 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7373 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7374 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7375 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7376 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7377 const char * optval
, int optlen
);
7378 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7379 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7381 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7382 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7383 struct sockaddr
* from
, int * fromlen
);
7384 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7385 const struct sockaddr
* to
, int tolen
);
7387 int (PASCAL
*pfn_getaddrinfo
) (const char *, const char *,
7388 const struct addrinfo
*, struct addrinfo
**);
7389 void (PASCAL
*pfn_freeaddrinfo
) (struct addrinfo
*);
7391 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7392 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7393 #ifndef HANDLE_FLAG_INHERIT
7394 #define HANDLE_FLAG_INHERIT 1
7398 static int winsock_inuse
;
7400 BOOL
term_winsock (void);
7405 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7407 release_listen_threads ();
7408 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7409 after WSAStartup returns successfully, but it seems reasonable
7410 to allow unloading winsock anyway in that case. */
7411 if (pfn_WSACleanup () == 0 ||
7412 pfn_WSAGetLastError () == WSAENETDOWN
)
7414 if (FreeLibrary (winsock_lib
))
7423 init_winsock (int load_now
)
7425 WSADATA winsockData
;
7427 if (winsock_lib
!= NULL
)
7430 pfn_SetHandleInformation
7431 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7432 "SetHandleInformation");
7434 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7436 if (winsock_lib
!= NULL
)
7438 /* dynamically link to socket functions */
7440 #define LOAD_PROC(fn) \
7441 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7444 LOAD_PROC (WSAStartup
);
7445 LOAD_PROC (WSASetLastError
);
7446 LOAD_PROC (WSAGetLastError
);
7447 LOAD_PROC (WSAEventSelect
);
7448 LOAD_PROC (WSAEnumNetworkEvents
);
7449 LOAD_PROC (WSACreateEvent
);
7450 LOAD_PROC (WSACloseEvent
);
7453 LOAD_PROC (connect
);
7454 LOAD_PROC (ioctlsocket
);
7457 LOAD_PROC (closesocket
);
7458 LOAD_PROC (shutdown
);
7461 LOAD_PROC (inet_addr
);
7462 LOAD_PROC (gethostname
);
7463 LOAD_PROC (gethostbyname
);
7464 LOAD_PROC (getservbyname
);
7465 LOAD_PROC (getpeername
);
7466 LOAD_PROC (WSACleanup
);
7467 LOAD_PROC (setsockopt
);
7469 LOAD_PROC (getsockname
);
7471 LOAD_PROC (recvfrom
);
7475 /* Try loading functions not available before XP. */
7476 pfn_getaddrinfo
= (void *) GetProcAddress (winsock_lib
, "getaddrinfo");
7477 pfn_freeaddrinfo
= (void *) GetProcAddress (winsock_lib
, "freeaddrinfo");
7478 /* Paranoia: these two functions should go together, so if one
7479 is absent, we cannot use the other. */
7480 if (pfn_getaddrinfo
== NULL
)
7481 pfn_freeaddrinfo
= NULL
;
7482 else if (pfn_freeaddrinfo
== NULL
)
7483 pfn_getaddrinfo
= NULL
;
7485 /* specify version 1.1 of winsock */
7486 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7488 if (winsockData
.wVersion
!= 0x101)
7493 /* Report that winsock exists and is usable, but leave
7494 socket functions disabled. I am assuming that calling
7495 WSAStartup does not require any network interaction,
7496 and in particular does not cause or require a dial-up
7497 connection to be established. */
7500 FreeLibrary (winsock_lib
);
7508 FreeLibrary (winsock_lib
);
7518 /* Function to map winsock error codes to errno codes for those errno
7519 code defined in errno.h (errno values not defined by errno.h are
7520 already in nt/inc/sys/socket.h). */
7527 if (winsock_lib
== NULL
)
7530 wsa_err
= pfn_WSAGetLastError ();
7534 case WSAEACCES
: errno
= EACCES
; break;
7535 case WSAEBADF
: errno
= EBADF
; break;
7536 case WSAEFAULT
: errno
= EFAULT
; break;
7537 case WSAEINTR
: errno
= EINTR
; break;
7538 case WSAEINVAL
: errno
= EINVAL
; break;
7539 case WSAEMFILE
: errno
= EMFILE
; break;
7540 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7541 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7542 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7543 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7544 default: errno
= wsa_err
; break;
7552 if (winsock_lib
!= NULL
)
7553 pfn_WSASetLastError (0);
7556 /* Extend strerror to handle the winsock-specific error codes. */
7560 } _wsa_errlist
[] = {
7561 {WSAEINTR
, "Interrupted function call"},
7562 {WSAEBADF
, "Bad file descriptor"},
7563 {WSAEACCES
, "Permission denied"},
7564 {WSAEFAULT
, "Bad address"},
7565 {WSAEINVAL
, "Invalid argument"},
7566 {WSAEMFILE
, "Too many open files"},
7568 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7569 {WSAEINPROGRESS
, "Operation now in progress"},
7570 {WSAEALREADY
, "Operation already in progress"},
7571 {WSAENOTSOCK
, "Socket operation on non-socket"},
7572 {WSAEDESTADDRREQ
, "Destination address required"},
7573 {WSAEMSGSIZE
, "Message too long"},
7574 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7575 {WSAENOPROTOOPT
, "Bad protocol option"},
7576 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7577 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7578 {WSAEOPNOTSUPP
, "Operation not supported"},
7579 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7580 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7581 {WSAEADDRINUSE
, "Address already in use"},
7582 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7583 {WSAENETDOWN
, "Network is down"},
7584 {WSAENETUNREACH
, "Network is unreachable"},
7585 {WSAENETRESET
, "Network dropped connection on reset"},
7586 {WSAECONNABORTED
, "Software caused connection abort"},
7587 {WSAECONNRESET
, "Connection reset by peer"},
7588 {WSAENOBUFS
, "No buffer space available"},
7589 {WSAEISCONN
, "Socket is already connected"},
7590 {WSAENOTCONN
, "Socket is not connected"},
7591 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7592 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7593 {WSAETIMEDOUT
, "Connection timed out"},
7594 {WSAECONNREFUSED
, "Connection refused"},
7595 {WSAELOOP
, "Network loop"}, /* not sure */
7596 {WSAENAMETOOLONG
, "Name is too long"},
7597 {WSAEHOSTDOWN
, "Host is down"},
7598 {WSAEHOSTUNREACH
, "No route to host"},
7599 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7600 {WSAEPROCLIM
, "Too many processes"},
7601 {WSAEUSERS
, "Too many users"}, /* not sure */
7602 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7603 {WSAESTALE
, "Data is stale"}, /* not sure */
7604 {WSAEREMOTE
, "Remote error"}, /* not sure */
7606 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7607 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7608 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7609 {WSAEDISCON
, "Graceful shutdown in progress"},
7611 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7612 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7613 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7614 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7615 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7616 {WSASYSCALLFAILURE
, "System call failure"},
7617 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7618 {WSATYPE_NOT_FOUND
, "Class type not found"},
7619 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7620 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7621 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7624 {WSAHOST_NOT_FOUND
, "Host not found"},
7625 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7626 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7627 {WSANO_DATA
, "Valid name, no data record of requested type"},
7633 sys_strerror (int error_no
)
7636 static char unknown_msg
[40];
7638 if (error_no
>= 0 && error_no
< sys_nerr
)
7639 return sys_errlist
[error_no
];
7641 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7642 if (_wsa_errlist
[i
].errnum
== error_no
)
7643 return (char *)_wsa_errlist
[i
].msg
;
7645 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7649 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7650 but I believe the method of keeping the socket handle separate (and
7651 insuring it is not inheritable) is the correct one. */
7653 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7655 static int socket_to_fd (SOCKET s
);
7658 sys_socket (int af
, int type
, int protocol
)
7662 if (winsock_lib
== NULL
)
7670 /* call the real socket function */
7671 s
= pfn_socket (af
, type
, protocol
);
7673 if (s
!= INVALID_SOCKET
)
7674 return socket_to_fd (s
);
7680 /* Convert a SOCKET to a file descriptor. */
7682 socket_to_fd (SOCKET s
)
7687 /* Although under NT 3.5 _open_osfhandle will accept a socket
7688 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7689 that does not work under NT 3.1. However, we can get the same
7690 effect by using a backdoor function to replace an existing
7691 descriptor handle with the one we want. */
7693 /* allocate a file descriptor (with appropriate flags) */
7694 fd
= _open ("NUL:", _O_RDWR
);
7697 /* Make a non-inheritable copy of the socket handle. Note
7698 that it is possible that sockets aren't actually kernel
7699 handles, which appears to be the case on Windows 9x when
7700 the MS Proxy winsock client is installed. */
7702 /* Apparently there is a bug in NT 3.51 with some service
7703 packs, which prevents using DuplicateHandle to make a
7704 socket handle non-inheritable (causes WSACleanup to
7705 hang). The work-around is to use SetHandleInformation
7706 instead if it is available and implemented. */
7707 if (pfn_SetHandleInformation
)
7709 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7713 HANDLE parent
= GetCurrentProcess ();
7714 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7716 if (DuplicateHandle (parent
,
7722 DUPLICATE_SAME_ACCESS
))
7724 /* It is possible that DuplicateHandle succeeds even
7725 though the socket wasn't really a kernel handle,
7726 because a real handle has the same value. So
7727 test whether the new handle really is a socket. */
7728 unsigned long nonblocking
= 0;
7729 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7731 pfn_closesocket (s
);
7736 CloseHandle (new_s
);
7741 eassert (fd
< MAXDESC
);
7742 fd_info
[fd
].hnd
= (HANDLE
) s
;
7744 /* set our own internal flags */
7745 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7751 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7753 /* attach child_process to fd_info */
7754 if (fd_info
[ fd
].cp
!= NULL
)
7756 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7760 fd_info
[ fd
].cp
= cp
;
7763 winsock_inuse
++; /* count open sockets */
7771 pfn_closesocket (s
);
7777 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7779 if (winsock_lib
== NULL
)
7782 return SOCKET_ERROR
;
7786 if (fd_info
[s
].flags
& FILE_SOCKET
)
7788 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7789 if (rc
== SOCKET_ERROR
)
7794 return SOCKET_ERROR
;
7798 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7800 if (winsock_lib
== NULL
)
7803 return SOCKET_ERROR
;
7807 if (fd_info
[s
].flags
& FILE_SOCKET
)
7809 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7810 if (rc
== SOCKET_ERROR
)
7813 /* If this is a non-blocking 'connect', set the bit in flags
7814 that will tell reader_thread to wait for connection
7815 before trying to read. */
7816 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7818 errno
= EINPROGRESS
; /* that's what process.c expects */
7819 fd_info
[s
].flags
|= FILE_CONNECT
;
7825 return SOCKET_ERROR
;
7829 sys_htons (u_short hostshort
)
7831 return (winsock_lib
!= NULL
) ?
7832 pfn_htons (hostshort
) : hostshort
;
7836 sys_ntohs (u_short netshort
)
7838 return (winsock_lib
!= NULL
) ?
7839 pfn_ntohs (netshort
) : netshort
;
7843 sys_inet_addr (const char * cp
)
7845 return (winsock_lib
!= NULL
) ?
7846 pfn_inet_addr (cp
) : INADDR_NONE
;
7850 sys_gethostname (char * name
, int namelen
)
7852 if (winsock_lib
!= NULL
)
7857 retval
= pfn_gethostname (name
, namelen
);
7858 if (retval
== SOCKET_ERROR
)
7863 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7864 return !GetComputerName (name
, (DWORD
*)&namelen
);
7867 return SOCKET_ERROR
;
7871 sys_gethostbyname (const char * name
)
7873 struct hostent
* host
;
7874 int h_err
= h_errno
;
7876 if (winsock_lib
== NULL
)
7878 h_errno
= NO_RECOVERY
;
7884 host
= pfn_gethostbyname (name
);
7896 sys_getservbyname (const char * name
, const char * proto
)
7898 struct servent
* serv
;
7900 if (winsock_lib
== NULL
)
7907 serv
= pfn_getservbyname (name
, proto
);
7914 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7916 if (winsock_lib
== NULL
)
7919 return SOCKET_ERROR
;
7923 if (fd_info
[s
].flags
& FILE_SOCKET
)
7925 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7926 if (rc
== SOCKET_ERROR
)
7931 return SOCKET_ERROR
;
7935 sys_getaddrinfo (const char *node
, const char *service
,
7936 const struct addrinfo
*hints
, struct addrinfo
**res
)
7940 if (winsock_lib
== NULL
)
7943 return SOCKET_ERROR
;
7947 if (pfn_getaddrinfo
)
7948 rc
= pfn_getaddrinfo (node
, service
, hints
, res
);
7952 struct hostent
*host_info
;
7953 struct gai_storage
{
7954 struct addrinfo addrinfo
;
7955 struct sockaddr_in sockaddr_in
;
7958 /* We don't (yet) support any flags, as Emacs doesn't need that. */
7959 if (hints
&& hints
->ai_flags
!= 0)
7961 /* NODE cannot be NULL, since process.c has fallbacks for that. */
7963 return WSAHOST_NOT_FOUND
;
7967 const char *protocol
=
7968 (hints
&& hints
->ai_socktype
== SOCK_DGRAM
) ? "udp" : "tcp";
7969 struct servent
*srv
= sys_getservbyname (service
, protocol
);
7973 else if (*service
>= '0' && *service
<= '9')
7977 port
= strtoul (service
, &endp
, 10);
7978 if (*endp
|| port
> 65536)
7979 return WSAHOST_NOT_FOUND
;
7980 port
= sys_htons ((unsigned short) port
);
7983 return WSAHOST_NOT_FOUND
;
7986 gai_storage
= xzalloc (sizeof *gai_storage
);
7987 gai_storage
->sockaddr_in
.sin_port
= port
;
7988 host_info
= sys_gethostbyname (node
);
7991 memcpy (&gai_storage
->sockaddr_in
.sin_addr
,
7992 host_info
->h_addr
, host_info
->h_length
);
7993 gai_storage
->sockaddr_in
.sin_family
= host_info
->h_addrtype
;
7997 /* Attempt to interpret host as numeric inet address. */
7998 unsigned long numeric_addr
= sys_inet_addr (node
);
8000 if (numeric_addr
== -1)
8003 return WSAHOST_NOT_FOUND
;
8006 memcpy (&gai_storage
->sockaddr_in
.sin_addr
, &numeric_addr
,
8007 sizeof (gai_storage
->sockaddr_in
.sin_addr
));
8008 gai_storage
->sockaddr_in
.sin_family
= (hints
) ? hints
->ai_family
: 0;
8011 gai_storage
->addrinfo
.ai_addr
=
8012 (struct sockaddr
*)&gai_storage
->sockaddr_in
;
8013 gai_storage
->addrinfo
.ai_addrlen
= sizeof (gai_storage
->sockaddr_in
);
8014 gai_storage
->addrinfo
.ai_protocol
= (hints
) ? hints
->ai_protocol
: 0;
8015 gai_storage
->addrinfo
.ai_socktype
= (hints
) ? hints
->ai_socktype
: 0;
8016 gai_storage
->addrinfo
.ai_family
= gai_storage
->sockaddr_in
.sin_family
;
8017 gai_storage
->addrinfo
.ai_next
= NULL
;
8019 *res
= &gai_storage
->addrinfo
;
8027 sys_freeaddrinfo (struct addrinfo
*ai
)
8029 if (winsock_lib
== NULL
)
8036 if (pfn_freeaddrinfo
)
8037 pfn_freeaddrinfo (ai
);
8040 eassert (ai
->ai_next
== NULL
);
8046 sys_shutdown (int s
, int how
)
8048 if (winsock_lib
== NULL
)
8051 return SOCKET_ERROR
;
8055 if (fd_info
[s
].flags
& FILE_SOCKET
)
8057 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
8058 if (rc
== SOCKET_ERROR
)
8063 return SOCKET_ERROR
;
8067 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
8069 if (winsock_lib
== NULL
)
8072 return SOCKET_ERROR
;
8076 if (fd_info
[s
].flags
& FILE_SOCKET
)
8078 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
8079 (const char *)optval
, optlen
);
8080 if (rc
== SOCKET_ERROR
)
8085 return SOCKET_ERROR
;
8089 sys_listen (int s
, int backlog
)
8091 if (winsock_lib
== NULL
)
8094 return SOCKET_ERROR
;
8098 if (fd_info
[s
].flags
& FILE_SOCKET
)
8100 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
8101 if (rc
== SOCKET_ERROR
)
8104 fd_info
[s
].flags
|= FILE_LISTEN
;
8108 return SOCKET_ERROR
;
8112 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
8114 if (winsock_lib
== NULL
)
8117 return SOCKET_ERROR
;
8121 if (fd_info
[s
].flags
& FILE_SOCKET
)
8123 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
8124 if (rc
== SOCKET_ERROR
)
8129 return SOCKET_ERROR
;
8133 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
8135 if (winsock_lib
== NULL
)
8142 if (fd_info
[s
].flags
& FILE_LISTEN
)
8144 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
8146 if (t
== INVALID_SOCKET
)
8149 fd
= socket_to_fd (t
);
8153 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8154 ResetEvent (fd_info
[s
].cp
->char_avail
);
8163 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
8164 struct sockaddr
* from
, int * fromlen
)
8166 if (winsock_lib
== NULL
)
8169 return SOCKET_ERROR
;
8173 if (fd_info
[s
].flags
& FILE_SOCKET
)
8175 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
8176 if (rc
== SOCKET_ERROR
)
8181 return SOCKET_ERROR
;
8185 sys_sendto (int s
, const char * buf
, int len
, int flags
,
8186 const struct sockaddr
* to
, int tolen
)
8188 if (winsock_lib
== NULL
)
8191 return SOCKET_ERROR
;
8195 if (fd_info
[s
].flags
& FILE_SOCKET
)
8197 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
8198 if (rc
== SOCKET_ERROR
)
8203 return SOCKET_ERROR
;
8206 /* Windows does not have an fcntl function. Provide an implementation
8207 good enough for Emacs. */
8209 fcntl (int s
, int cmd
, int options
)
8211 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
8212 invoked in a context where fd1 is closed and all descriptors less
8213 than fd1 are open, so sys_dup is an adequate implementation. */
8214 if (cmd
== F_DUPFD_CLOEXEC
)
8218 if (fd_info
[s
].flags
& FILE_SOCKET
)
8220 if (winsock_lib
== NULL
)
8226 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8228 unsigned long nblock
= 1;
8229 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
8230 if (rc
== SOCKET_ERROR
)
8232 /* Keep track of the fact that we set this to non-blocking. */
8233 fd_info
[s
].flags
|= FILE_NDELAY
;
8239 return SOCKET_ERROR
;
8242 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
8243 == (FILE_PIPE
| FILE_WRITE
))
8245 /* Force our writes to pipes be non-blocking. */
8246 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
8248 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
8249 DWORD pipe_mode
= PIPE_NOWAIT
;
8251 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
8253 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8254 return SOCKET_ERROR
;
8256 fd_info
[s
].flags
|= FILE_NDELAY
;
8262 return SOCKET_ERROR
;
8266 return SOCKET_ERROR
;
8270 /* Shadow main io functions: we need to handle pipes and sockets more
8284 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
8286 child_process
* cp
= fd_info
[fd
].cp
;
8288 fd_info
[fd
].cp
= NULL
;
8290 if (CHILD_ACTIVE (cp
))
8292 /* if last descriptor to active child_process then cleanup */
8294 for (i
= 0; i
< MAXDESC
; i
++)
8298 if (fd_info
[i
].cp
== cp
)
8303 if (fd_info
[fd
].flags
& FILE_SOCKET
)
8305 if (winsock_lib
== NULL
) emacs_abort ();
8307 pfn_shutdown (SOCK_HANDLE (fd
), 2);
8308 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
8310 winsock_inuse
--; /* count open sockets */
8312 /* If the process handle is NULL, it's either a socket
8313 or serial connection, or a subprocess that was
8314 already reaped by reap_subprocess, but whose
8315 resources were not yet freed, because its output was
8316 not fully read yet by the time it was reaped. (This
8317 usually happens with async subprocesses whose output
8318 is being read by Emacs.) Otherwise, this process was
8319 not reaped yet, so we set its FD to a negative value
8320 to make sure sys_select will eventually get to
8321 calling the SIGCHLD handler for it, which will then
8322 invoke waitpid and reap_subprocess. */
8323 if (cp
->procinfo
.hProcess
== NULL
)
8331 if (fd
>= 0 && fd
< MAXDESC
)
8332 fd_info
[fd
].flags
= 0;
8334 /* Note that sockets do not need special treatment here (at least on
8335 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
8336 closesocket is equivalent to CloseHandle, which is to be expected
8337 because socket handles are fully fledged kernel handles. */
8349 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8351 /* duplicate our internal info as well */
8352 fd_info
[new_fd
] = fd_info
[fd
];
8358 sys_dup2 (int src
, int dst
)
8362 if (dst
< 0 || dst
>= MAXDESC
)
8368 /* MS _dup2 seems to have weird side effect when invoked with 2
8369 identical arguments: an attempt to fclose the corresponding stdio
8370 stream after that hangs (we do close standard streams in
8371 init_ntproc). Attempt to avoid that by not calling _dup2 that
8372 way: if SRC is valid, we know that dup2 should be a no-op, so do
8373 nothing and return DST. */
8376 if ((HANDLE
)_get_osfhandle (src
) == INVALID_HANDLE_VALUE
)
8384 /* Make sure we close the destination first if it's a pipe or socket. */
8385 if (fd_info
[dst
].flags
!= 0)
8388 rc
= _dup2 (src
, dst
);
8391 /* Duplicate our internal info as well. */
8392 fd_info
[dst
] = fd_info
[src
];
8394 return rc
== 0 ? dst
: rc
;
8398 pipe2 (int * phandles
, int pipe2_flags
)
8402 unsigned pipe_size
= 0;
8404 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8406 /* Allow Lisp to override the default buffer size of the pipe. */
8407 if (w32_pipe_buffer_size
> 0 && w32_pipe_buffer_size
< UINT_MAX
)
8408 pipe_size
= w32_pipe_buffer_size
;
8410 /* make pipe handles non-inheritable; when we spawn a child, we
8411 replace the relevant handle with an inheritable one. Also put
8412 pipes into binary mode; we will do text mode translation ourselves
8414 rc
= _pipe (phandles
, pipe_size
, _O_NOINHERIT
| _O_BINARY
);
8418 /* Protect against overflow, since Windows can open more handles than
8419 our fd_info array has room for. */
8420 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8422 _close (phandles
[0]);
8423 _close (phandles
[1]);
8429 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8430 fd_info
[phandles
[0]].flags
= flags
;
8432 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8433 fd_info
[phandles
[1]].flags
= flags
;
8440 /* Function to do blocking read of one byte, needed to implement
8441 select. It is only allowed on communication ports, sockets, or
8444 _sys_read_ahead (int fd
)
8449 if (fd
< 0 || fd
>= MAXDESC
)
8450 return STATUS_READ_ERROR
;
8452 cp
= fd_info
[fd
].cp
;
8454 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8455 return STATUS_READ_ERROR
;
8457 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8458 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8460 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8464 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8465 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8466 cp
->status
= STATUS_READ_IN_PROGRESS
;
8468 if (fd_info
[fd
].flags
& FILE_PIPE
)
8470 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8472 /* Give subprocess time to buffer some more output for us before
8473 reporting that input is available; we need this because Windows 95
8474 connects DOS programs to pipes by making the pipe appear to be
8475 the normal console stdout - as a result most DOS programs will
8476 write to stdout without buffering, ie. one character at a
8477 time. Even some W32 programs do this - "dir" in a command
8478 shell on NT is very slow if we don't do this. */
8481 int wait
= w32_pipe_read_delay
;
8487 /* Yield remainder of our time slice, effectively giving a
8488 temporary priority boost to the child process. */
8492 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8494 HANDLE hnd
= fd_info
[fd
].hnd
;
8495 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8498 /* Configure timeouts for blocking read. */
8499 if (!GetCommTimeouts (hnd
, &ct
))
8501 cp
->status
= STATUS_READ_ERROR
;
8502 return STATUS_READ_ERROR
;
8504 ct
.ReadIntervalTimeout
= 0;
8505 ct
.ReadTotalTimeoutMultiplier
= 0;
8506 ct
.ReadTotalTimeoutConstant
= 0;
8507 if (!SetCommTimeouts (hnd
, &ct
))
8509 cp
->status
= STATUS_READ_ERROR
;
8510 return STATUS_READ_ERROR
;
8513 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8515 if (GetLastError () != ERROR_IO_PENDING
)
8517 cp
->status
= STATUS_READ_ERROR
;
8518 return STATUS_READ_ERROR
;
8520 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8522 cp
->status
= STATUS_READ_ERROR
;
8523 return STATUS_READ_ERROR
;
8527 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8529 unsigned long nblock
= 0;
8530 /* We always want this to block, so temporarily disable NDELAY. */
8531 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8532 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8534 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8536 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8539 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8543 if (rc
== sizeof (char))
8544 cp
->status
= STATUS_READ_SUCCEEDED
;
8546 cp
->status
= STATUS_READ_FAILED
;
8552 _sys_wait_accept (int fd
)
8558 if (fd
< 0 || fd
>= MAXDESC
)
8559 return STATUS_READ_ERROR
;
8561 cp
= fd_info
[fd
].cp
;
8563 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8564 return STATUS_READ_ERROR
;
8566 cp
->status
= STATUS_READ_FAILED
;
8568 hEv
= pfn_WSACreateEvent ();
8569 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8570 if (rc
!= SOCKET_ERROR
)
8573 rc
= WaitForSingleObject (hEv
, 500);
8575 } while (rc
== WAIT_TIMEOUT
8576 && cp
->status
!= STATUS_READ_ERROR
8578 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8579 if (rc
== WAIT_OBJECT_0
)
8580 cp
->status
= STATUS_READ_SUCCEEDED
;
8582 pfn_WSACloseEvent (hEv
);
8588 _sys_wait_connect (int fd
)
8594 if (fd
< 0 || fd
>= MAXDESC
)
8595 return STATUS_READ_ERROR
;
8597 cp
= fd_info
[fd
].cp
;
8598 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8599 return STATUS_READ_ERROR
;
8601 cp
->status
= STATUS_READ_FAILED
;
8603 hEv
= pfn_WSACreateEvent ();
8604 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8605 if (rc
!= SOCKET_ERROR
)
8608 rc
= WaitForSingleObject (hEv
, 500);
8610 } while (rc
== WAIT_TIMEOUT
8611 && cp
->status
!= STATUS_READ_ERROR
8613 if (rc
== WAIT_OBJECT_0
)
8615 /* We've got an event, but it could be a successful
8616 connection, or it could be a failure. Find out
8618 WSANETWORKEVENTS events
;
8620 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8621 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8622 && events
.iErrorCode
[FD_CONNECT_BIT
])
8624 cp
->status
= STATUS_CONNECT_FAILED
;
8625 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8629 cp
->status
= STATUS_READ_SUCCEEDED
;
8633 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8636 pfn_WSACloseEvent (hEv
);
8642 sys_read (int fd
, char * buffer
, unsigned int count
)
8647 char * orig_buffer
= buffer
;
8655 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8657 child_process
*cp
= fd_info
[fd
].cp
;
8659 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8667 /* re-read CR carried over from last read */
8668 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8670 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8674 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8677 /* presence of a child_process structure means we are operating in
8678 non-blocking mode - otherwise we just call _read directly.
8679 Note that the child_process structure might be missing because
8680 reap_subprocess has been called; in this case the pipe is
8681 already broken, so calling _read on it is okay. */
8684 int current_status
= cp
->status
;
8686 switch (current_status
)
8688 case STATUS_READ_FAILED
:
8689 case STATUS_READ_ERROR
:
8690 /* report normal EOF if nothing in buffer */
8692 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8695 case STATUS_READ_READY
:
8696 case STATUS_READ_IN_PROGRESS
:
8698 /* This happens all the time during GnuTLS handshake
8699 with the remote, evidently because GnuTLS waits for
8700 the read to complete by retrying the read operation
8701 upon EAGAIN. So I'm disabling the DebPrint to avoid
8702 wasting cycles on something that is not a real
8703 problem. Enable if you need to debug something that
8705 DebPrint (("sys_read called when read is in progress %d\n",
8708 errno
= EWOULDBLOCK
;
8711 case STATUS_READ_SUCCEEDED
:
8712 /* consume read-ahead char */
8713 *buffer
++ = cp
->chr
;
8716 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8717 ResetEvent (cp
->char_avail
);
8719 case STATUS_READ_ACKNOWLEDGED
:
8720 case STATUS_CONNECT_FAILED
:
8724 DebPrint (("sys_read: bad status %d\n", current_status
));
8729 if (fd_info
[fd
].flags
& FILE_PIPE
)
8731 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8732 to_read
= min (waiting
, (DWORD
) count
);
8735 nchars
+= _read (fd
, buffer
, to_read
);
8737 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8739 HANDLE hnd
= fd_info
[fd
].hnd
;
8740 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8746 /* Configure timeouts for non-blocking read. */
8747 if (!GetCommTimeouts (hnd
, &ct
))
8752 ct
.ReadIntervalTimeout
= MAXDWORD
;
8753 ct
.ReadTotalTimeoutMultiplier
= 0;
8754 ct
.ReadTotalTimeoutConstant
= 0;
8755 if (!SetCommTimeouts (hnd
, &ct
))
8761 if (!ResetEvent (ovl
->hEvent
))
8766 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8768 if (GetLastError () != ERROR_IO_PENDING
)
8773 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8782 else /* FILE_SOCKET */
8784 if (winsock_lib
== NULL
) emacs_abort ();
8786 /* When a non-blocking 'connect' call fails,
8787 wait_reading_process_output detects this by calling
8788 'getpeername', and then attempts to obtain the connection
8789 error code by trying to read 1 byte from the socket. If
8790 we try to serve that read by calling 'recv' below, the
8791 error we get is a generic WSAENOTCONN, not the actual
8792 connection error. So instead, we use the actual error
8793 code stashed by '_sys_wait_connect' in cp->errcode.
8794 Alternatively, we could have used 'getsockopt', like on
8795 GNU/Linux, but: (a) I have no idea whether the winsock
8796 version could hang, as it does "on some systems" (see the
8797 comment in process.c); and (b) 'getsockopt' on Windows is
8798 documented to clear the socket error for the entire
8799 process, which I'm not sure is TRT; FIXME. */
8800 if (current_status
== STATUS_CONNECT_FAILED
8801 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8802 && cp
->errcode
!= 0)
8804 pfn_WSASetLastError (cp
->errcode
);
8808 /* Do the equivalent of a non-blocking read. */
8809 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8810 if (waiting
== 0 && nchars
== 0)
8812 errno
= EWOULDBLOCK
;
8818 /* always use binary mode for sockets */
8819 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8820 if (res
== SOCKET_ERROR
)
8823 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8824 errno
, SOCK_HANDLE (fd
)));
8833 int nread
= _read (fd
, buffer
, count
);
8836 else if (nchars
== 0)
8841 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8842 /* Perform text mode translation if required. */
8843 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8845 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8846 /* If buffer contains only CR, return that. To be absolutely
8847 sure we should attempt to read the next char, but in
8848 practice a CR to be followed by LF would not appear by
8849 itself in the buffer. */
8850 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8852 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8858 nchars
= _read (fd
, buffer
, count
);
8863 /* From w32xfns.c */
8864 extern HANDLE interrupt_handle
;
8867 sys_write (int fd
, const void * buffer
, unsigned int count
)
8878 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8880 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8886 /* Perform text mode translation if required. */
8887 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8890 const unsigned char * src
= buffer
;
8891 unsigned char * dst
;
8894 SAFE_NALLOCA (tmpbuf
, 2, count
);
8895 dst
= (unsigned char *)tmpbuf
;
8899 unsigned char *next
;
8900 /* Copy next line or remaining bytes. */
8901 next
= _memccpy (dst
, src
, '\n', nbytes
);
8904 /* Copied one line ending with '\n'. */
8905 int copied
= next
- dst
;
8908 /* Insert '\r' before '\n'. */
8915 /* Copied remaining partial line -> now finished. */
8922 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8924 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8925 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8926 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8929 /* This is async (a.k.a. "overlapped") I/O, so the return value
8930 of FALSE from WriteFile means either an error or the output
8931 will be completed asynchronously (ERROR_IO_PENDING). */
8932 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8934 if (GetLastError () != ERROR_IO_PENDING
)
8941 /* Wait for the write to complete, and watch C-g while
8943 if (detect_input_pending ())
8944 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8945 INFINITE
, QS_ALLINPUT
);
8947 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8951 /* User pressed C-g, cancel write, then leave.
8952 Don't bother cleaning up as we may only get stuck
8953 in buggy drivers. */
8954 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8956 errno
= EIO
; /* Why not EINTR? */
8959 case WAIT_OBJECT_0
+ 1:
8960 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8970 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8972 unsigned long nblock
= 0;
8973 if (winsock_lib
== NULL
) emacs_abort ();
8975 child_process
*cp
= fd_info
[fd
].cp
;
8977 /* If this is a non-blocking socket whose connection is in
8978 progress or terminated with an error already, return the
8979 proper error code to the caller. */
8980 if (cp
!= NULL
&& (fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8982 /* In case connection is in progress, ENOTCONN that would
8983 result from calling pfn_send is not what callers expect. */
8984 if (cp
->status
!= STATUS_CONNECT_FAILED
)
8986 errno
= EWOULDBLOCK
;
8989 /* In case connection failed, use the actual error code
8990 stashed by '_sys_wait_connect' in cp->errcode. */
8991 else if (cp
->errcode
!= 0)
8993 pfn_WSASetLastError (cp
->errcode
);
8999 /* TODO: implement select() properly so non-blocking I/O works. */
9000 /* For now, make sure the write blocks. */
9001 if (fd_info
[fd
].flags
& FILE_NDELAY
)
9002 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
9004 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
9006 if (nchars
== SOCKET_ERROR
)
9009 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
9010 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
9013 /* Set the socket back to non-blocking if it was before,
9014 for other operations that support it. */
9015 if (fd_info
[fd
].flags
& FILE_NDELAY
)
9018 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
9023 /* Some networked filesystems don't like too large writes, so
9024 break them into smaller chunks. See the Comments section of
9025 the MSDN documentation of WriteFile for details behind the
9026 choice of the value of CHUNK below. See also the thread
9027 http://thread.gmane.org/gmane.comp.version-control.git/145294
9028 in the git mailing list. */
9029 const unsigned char *p
= buffer
;
9030 const bool is_pipe
= (fd
< MAXDESC
9031 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
9032 == (FILE_PIPE
| FILE_NDELAY
)));
9033 /* Some programs, notably Node.js's node.exe, seem to never
9034 completely empty the pipe, so writing more than the size of
9035 the pipe's buffer always returns ENOSPC, and we loop forever
9036 between send_process and here. As a workaround, write no
9037 more than the pipe's buffer can hold. */
9038 DWORD pipe_buffer_size
;
9041 if (!GetNamedPipeInfo ((HANDLE
)_get_osfhandle (fd
),
9042 NULL
, &pipe_buffer_size
, NULL
, NULL
))
9044 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
9045 pipe_buffer_size
= 4096;
9048 const unsigned chunk
= is_pipe
? pipe_buffer_size
: 30 * 1024 * 1024;
9054 unsigned this_chunk
= count
< chunk
? count
: chunk
;
9055 int n
= _write (fd
, p
, this_chunk
);
9061 /* When there's no buffer space in a pipe that is in the
9062 non-blocking mode, _write returns ENOSPC. We return
9063 EAGAIN instead, which should trigger the logic in
9064 send_process that enters waiting loop and calls
9065 wait_reading_process_output to allow process input to
9066 be accepted during the wait. Those calls to
9067 wait_reading_process_output allow sys_select to
9068 notice when process input becomes available, thus
9069 avoiding deadlock whereby each side of the pipe is
9070 blocked on write, waiting for the other party to read
9071 its end of the pipe. */
9072 if (errno
== ENOSPC
&& is_pipe
)
9078 else if (n
< this_chunk
)
9090 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
9092 /* Return information about network interface IFNAME, or about all
9093 interfaces (if IFNAME is nil). */
9095 network_interface_get_info (Lisp_Object ifname
)
9097 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
9098 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
9099 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
9100 Lisp_Object res
= Qnil
;
9102 if (retval
== ERROR_BUFFER_OVERFLOW
)
9104 ainfo
= xrealloc (ainfo
, ainfo_len
);
9105 retval
= get_adapters_info (ainfo
, &ainfo_len
);
9108 if (retval
== ERROR_SUCCESS
)
9110 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
9111 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
9113 struct sockaddr_in sa
;
9115 /* For the below, we need some winsock functions, so make sure
9116 the winsock DLL is loaded. If we cannot successfully load
9117 it, they will have no use of the information we provide,
9119 if (!winsock_lib
&& !init_winsock (1))
9122 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
9124 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
9126 /* Present Unix-compatible interface names, instead of the
9127 Windows names, which are really GUIDs not readable by
9129 static const char *ifmt
[] = {
9130 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9145 switch (adapter
->Type
)
9147 case MIB_IF_TYPE_ETHERNET
:
9148 /* Windows before Vista reports wireless adapters as
9149 Ethernet. Work around by looking at the Description
9151 if (strstr (adapter
->Description
, "Wireless "))
9154 if_num
= wlan_count
++;
9158 ifmt_idx
= ETHERNET
;
9159 if_num
= eth_count
++;
9162 case MIB_IF_TYPE_TOKENRING
:
9163 ifmt_idx
= TOKENRING
;
9164 if_num
= tr_count
++;
9166 case MIB_IF_TYPE_FDDI
:
9168 if_num
= fddi_count
++;
9170 case MIB_IF_TYPE_PPP
:
9172 if_num
= ppp_count
++;
9174 case MIB_IF_TYPE_SLIP
:
9176 if_num
= sl_count
++;
9178 case IF_TYPE_IEEE80211
:
9180 if_num
= wlan_count
++;
9182 case MIB_IF_TYPE_LOOPBACK
:
9185 ifmt_idx
= LOOPBACK
;
9186 if_num
= lo_count
++;
9192 ifmt_idx
= OTHER_IF
;
9193 if_num
= ifx_count
++;
9196 if (ifmt_idx
== NONE
)
9198 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
9200 sa
.sin_family
= AF_INET
;
9201 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
9202 if (ip_addr
== INADDR_NONE
)
9204 /* Bogus address, skip this interface. */
9207 sa
.sin_addr
.s_addr
= ip_addr
;
9210 res
= Fcons (Fcons (build_string (namebuf
),
9211 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9212 sizeof (struct sockaddr
))),
9214 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
9216 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
9217 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
9218 Lisp_Object flags
= Qnil
;
9222 /* Flags. We guess most of them by type, since the
9223 Windows flags are different and hard to get by. */
9224 flags
= Fcons (intern ("up"), flags
);
9225 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
9227 flags
= Fcons (intern ("broadcast"), flags
);
9228 flags
= Fcons (intern ("multicast"), flags
);
9230 flags
= Fcons (intern ("running"), flags
);
9231 if (ifmt_idx
== PPP
)
9233 flags
= Fcons (intern ("pointopoint"), flags
);
9234 flags
= Fcons (intern ("noarp"), flags
);
9236 if (adapter
->HaveWins
)
9237 flags
= Fcons (intern ("WINS"), flags
);
9238 if (adapter
->DhcpEnabled
)
9239 flags
= Fcons (intern ("dynamic"), flags
);
9241 res
= Fcons (flags
, res
);
9243 /* Hardware address and its family. */
9244 for (n
= 0; n
< adapter
->AddressLength
; n
++)
9245 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
9246 /* Windows does not support AF_LINK or AF_PACKET family
9247 of addresses. Use an arbitrary family number that is
9248 identical to what GNU/Linux returns. */
9249 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
9252 sa
.sin_family
= AF_INET
;
9253 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
9254 if (net_mask
!= INADDR_NONE
)
9256 sa
.sin_addr
.s_addr
= net_mask
;
9258 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9259 sizeof (struct sockaddr
)),
9263 res
= Fcons (Qnil
, res
);
9265 sa
.sin_family
= AF_INET
;
9266 if (ip_addr
!= INADDR_NONE
)
9268 /* Broadcast address is only reported by
9269 GetAdaptersAddresses, which is of limited
9270 availability. Generate it on our own. */
9271 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
9273 sa
.sin_addr
.s_addr
= bcast_addr
;
9275 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9276 sizeof (struct sockaddr
)),
9280 sa
.sin_addr
.s_addr
= ip_addr
;
9282 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9283 sizeof (struct sockaddr
)),
9287 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
9290 /* GetAdaptersInfo is documented to not report loopback
9291 interfaces, so we generate one out of thin air. */
9294 sa
.sin_family
= AF_INET
;
9298 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9299 res
= Fcons (Fcons (build_string ("lo"),
9300 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9301 sizeof (struct sockaddr
))),
9304 else if (strcmp (SSDATA (ifname
), "lo") == 0)
9306 res
= Fcons (Fcons (intern ("running"),
9307 Fcons (intern ("loopback"),
9308 Fcons (intern ("up"), Qnil
))), Qnil
);
9309 /* 772 is what 3 different GNU/Linux systems report for
9310 the loopback interface. */
9311 res
= Fcons (Fcons (make_number (772),
9312 Fmake_vector (make_number (6),
9315 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
9316 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9317 sizeof (struct sockaddr
)),
9319 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
9320 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9321 sizeof (struct sockaddr
)),
9323 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
9324 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
9325 sizeof (struct sockaddr
)),
9338 network_interface_list (void)
9340 return network_interface_get_info (Qnil
);
9344 network_interface_info (Lisp_Object ifname
)
9346 CHECK_STRING (ifname
);
9347 return network_interface_get_info (ifname
);
9351 /* Workhorse for w32-read-registry, which see. */
9353 w32_read_registry (HKEY rootkey
, Lisp_Object lkey
, Lisp_Object lname
)
9359 Lisp_Object val
, retval
;
9360 const char *key
, *value_name
;
9361 /* The following sizes are according to size limitations
9362 documented in MSDN. */
9363 wchar_t key_w
[255+1];
9364 wchar_t value_w
[16*1024+1];
9365 bool use_unicode
= is_windows_9x () == 0;
9369 Lisp_Object encoded_key
, encoded_vname
;
9371 /* Convert input strings to UTF-16. */
9372 encoded_key
= code_convert_string_norecord (lkey
, Qutf_16le
, 1);
9373 memcpy (key_w
, SSDATA (encoded_key
), SBYTES (encoded_key
));
9374 /* wchar_t strings need to be terminated by 2 null bytes. */
9375 key_w
[SBYTES (encoded_key
)/2] = L
'\0';
9376 encoded_vname
= code_convert_string_norecord (lname
, Qutf_16le
, 1);
9377 memcpy (value_w
, SSDATA (encoded_vname
), SBYTES (encoded_vname
));
9378 value_w
[SBYTES (encoded_vname
)/2] = L
'\0';
9380 /* Mirror the slashes, if required. */
9381 for (int i
= 0; i
< SBYTES (encoded_key
)/2; i
++)
9383 if (key_w
[i
] == L
'/')
9386 if ((status
= reg_open_key_ex_w (rootkey
, key_w
, 0,
9387 KEY_READ
, &hkey
)) == ERROR_NOT_SUPPORTED
9388 || (status
= reg_query_value_ex_w (hkey
, value_w
, NULL
, NULL
, NULL
,
9389 &vsize
)) == ERROR_NOT_SUPPORTED
9390 || status
!= ERROR_SUCCESS
)
9394 if (status
!= ERROR_NOT_SUPPORTED
)
9396 use_unicode
= 0; /* fall back to non-Unicode calls */
9401 /* Need to copy LKEY because we are going to modify it. */
9402 Lisp_Object local_lkey
= Fcopy_sequence (lkey
);
9404 /* Mirror the slashes. Note: this has to be done before
9405 encoding, because after encoding we cannot guarantee that a
9406 slash '/' always stands for itself, it could be part of some
9407 multibyte sequence. */
9408 for (int i
= 0; i
< SBYTES (local_lkey
); i
++)
9410 if (SSDATA (local_lkey
)[i
] == '/')
9411 SSDATA (local_lkey
)[i
] = '\\';
9414 key
= SSDATA (ENCODE_SYSTEM (local_lkey
));
9415 value_name
= SSDATA (ENCODE_SYSTEM (lname
));
9417 if ((status
= RegOpenKeyEx (rootkey
, key
, 0,
9418 KEY_READ
, &hkey
)) != ERROR_SUCCESS
9419 || (status
= RegQueryValueEx (hkey
, value_name
, NULL
,
9420 NULL
, NULL
, &vsize
)) != ERROR_SUCCESS
)
9428 pvalue
= xzalloc (vsize
);
9430 status
= reg_query_value_ex_w (hkey
, value_w
, NULL
, &vtype
, pvalue
, &vsize
);
9432 status
= RegQueryValueEx (hkey
, value_name
, NULL
, &vtype
, pvalue
, &vsize
);
9433 if (status
!= ERROR_SUCCESS
)
9446 retval
= INTEGER_TO_CONS (*((DWORD
*)pvalue
));
9449 retval
= INTEGER_TO_CONS (*((long long *)pvalue
));
9454 unsigned char *dbuf
= (unsigned char *)pvalue
;
9456 val
= make_uninit_vector (vsize
);
9457 for (i
= 0; i
< vsize
; i
++)
9458 ASET (val
, i
, make_number (dbuf
[i
]));
9466 /* pvalue ends with 2 null bytes, but we need only one,
9467 and AUTO_STRING_WITH_LEN will add it. */
9468 if (pvalue
[vsize
- 1] == '\0')
9470 AUTO_STRING_WITH_LEN (sval
, (char *)pvalue
, vsize
);
9471 retval
= from_unicode (sval
);
9475 /* Don't waste a byte on the terminating null character,
9476 since make_unibyte_string will add one anyway. */
9477 if (pvalue
[vsize
- 1] == '\0')
9479 retval
= DECODE_SYSTEM (make_unibyte_string (pvalue
, vsize
));
9485 wchar_t expanded_w
[32*1024];
9486 DWORD dsize
= sizeof (expanded_w
) / 2;
9487 DWORD produced
= expand_environment_strings_w ((wchar_t *)pvalue
,
9490 if (produced
> 0 && produced
< dsize
)
9492 AUTO_STRING_WITH_LEN (sval
, (char *)expanded_w
,
9494 retval
= from_unicode (sval
);
9498 if (pvalue
[vsize
- 1] == '\0')
9500 AUTO_STRING_WITH_LEN (sval
, (char *)pvalue
, vsize
);
9501 retval
= from_unicode (sval
);
9506 char expanded
[32*1024]; /* size limitation according to MSDN */
9507 DWORD produced
= ExpandEnvironmentStrings ((char *)pvalue
,
9510 if (produced
> 0 && produced
< sizeof (expanded
))
9511 retval
= make_unibyte_string (expanded
, produced
- 1);
9514 if (pvalue
[vsize
- 1] == '\0')
9516 retval
= make_unibyte_string (pvalue
, vsize
);
9519 retval
= DECODE_SYSTEM (retval
);
9525 wchar_t *wp
= (wchar_t *)pvalue
;
9529 size_t wslen
= wcslen (wp
);
9530 AUTO_STRING_WITH_LEN (sval
, (char *)wp
, wslen
* 2);
9531 val
= Fcons (from_unicode (sval
), val
);
9537 char *p
= (char *)pvalue
;
9541 size_t slen
= strlen (p
);
9543 val
= Fcons (DECODE_SYSTEM (make_unibyte_string (p
, slen
)), val
);
9548 retval
= Fnreverse (val
);
9551 error ("unsupported registry data type: %d", (int)vtype
);
9560 /* The Windows CRT functions are "optimized for speed", so they don't
9561 check for timezone and DST changes if they were last called less
9562 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
9563 all Emacs features that repeatedly call time functions (e.g.,
9564 display-time) are in real danger of missing timezone and DST
9565 changes. Calling tzset before each localtime call fixes that. */
9567 sys_localtime (const time_t *t
)
9570 return localtime (t
);
9575 /* Try loading LIBRARY_ID from the file(s) specified in
9576 Vdynamic_library_alist. If the library is loaded successfully,
9577 return the handle of the DLL, and record the filename in the
9578 property :loaded-from of LIBRARY_ID. If the library could not be
9579 found, or when it was already loaded (because the handle is not
9580 recorded anywhere, and so is lost after use), return NULL.
9582 We could also save the handle in :loaded-from, but currently
9583 there's no use case for it. */
9585 w32_delayed_load (Lisp_Object library_id
)
9587 HMODULE dll_handle
= NULL
;
9589 CHECK_SYMBOL (library_id
);
9591 if (CONSP (Vdynamic_library_alist
)
9592 && NILP (Fassq (library_id
, Vlibrary_cache
)))
9594 Lisp_Object found
= Qnil
;
9595 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
9598 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
9600 Lisp_Object dll
= XCAR (dlls
);
9601 char name
[MAX_UTF8_PATH
];
9605 dll
= ENCODE_FILE (dll
);
9606 if (w32_unicode_filenames
)
9608 wchar_t name_w
[MAX_PATH
];
9610 filename_to_utf16 (SSDATA (dll
), name_w
);
9611 dll_handle
= LoadLibraryW (name_w
);
9614 res
= GetModuleFileNameW (dll_handle
, name_w
,
9617 filename_from_utf16 (name_w
, name
);
9622 char name_a
[MAX_PATH
];
9624 filename_to_ansi (SSDATA (dll
), name_a
);
9625 dll_handle
= LoadLibraryA (name_a
);
9628 res
= GetModuleFileNameA (dll_handle
, name_a
,
9631 filename_from_ansi (name_a
, name
);
9636 ptrdiff_t len
= strlen (name
);
9639 /* Possibly truncated */
9640 ? make_specified_string (name
, -1, len
, 1)
9642 /* This prevents thread start and end notifications
9643 from being sent to the DLL, for every thread we
9644 start. We don't need those notifications because
9645 threads we create never use any of these DLLs, only
9646 the main thread uses them. This is supposed to
9647 speed up thread creation. */
9648 DisableThreadLibraryCalls (dll_handle
);
9653 Fput (library_id
, QCloaded_from
, found
);
9661 check_windows_init_file (void)
9663 /* A common indication that Emacs is not installed properly is when
9664 it cannot find the Windows installation file. If this file does
9665 not exist in the expected place, tell the user. */
9667 if (!noninteractive
&& !inhibit_window_system
9668 /* Vload_path is not yet initialized when we are loading
9670 && NILP (Vpurify_flag
))
9672 Lisp_Object init_file
;
9675 /* Implementation note: this function runs early during Emacs
9676 startup, before startup.el is run. So Vload_path is still in
9677 its initial unibyte form, but it holds UTF-8 encoded file
9678 names, since init_callproc was already called. So we do not
9679 need to ENCODE_FILE here, but we do need to convert the file
9680 names from UTF-8 to ANSI. */
9681 init_file
= build_string ("term/w32-win");
9682 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9685 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9686 char *init_file_name
= SSDATA (init_file
);
9687 char *load_path
= SSDATA (load_path_print
);
9688 char *buffer
= alloca (1024
9689 + strlen (init_file_name
)
9690 + strlen (load_path
));
9695 "The Emacs Windows initialization file \"%s.el\" "
9696 "could not be found in your Emacs installation. "
9697 "Emacs checked the following directories for this file:\n"
9699 "When Emacs cannot find this file, it usually means that it "
9700 "was not installed properly, or its distribution file was "
9701 "not unpacked properly.\nSee the README.W32 file in the "
9702 "top-level Emacs directory for more information.",
9703 init_file_name
, load_path
);
9704 needed
= pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
,
9705 buffer
, -1, NULL
, 0);
9708 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9710 pMultiByteToWideChar (CP_UTF8
, multiByteToWideCharFlags
, buffer
,
9712 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9713 NULL
, 0, NULL
, NULL
);
9716 char *msg_a
= alloca (needed
+ 1);
9718 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9725 "Emacs Abort Dialog",
9726 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9727 /* Use the low-level system abort. */
9738 term_ntproc (int ignored
)
9744 /* shutdown the socket interface if necessary */
9751 init_ntproc (int dumping
)
9753 sigset_t initial_mask
= 0;
9755 /* Initialize the socket interface now if available and requested by
9756 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9757 delayed until open-network-stream is called (w32-has-winsock can
9758 also be used to dynamically load or reload winsock).
9760 Conveniently, init_environment is called before us, so
9761 PRELOAD_WINSOCK can be set in the registry. */
9763 /* Always initialize this correctly. */
9766 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9767 init_winsock (TRUE
);
9769 /* Initial preparation for subprocess support: replace our standard
9770 handles with non-inheritable versions. */
9773 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9774 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9775 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9777 parent
= GetCurrentProcess ();
9779 /* ignore errors when duplicating and closing; typically the
9780 handles will be invalid when running as a gui program. */
9781 DuplicateHandle (parent
,
9782 GetStdHandle (STD_INPUT_HANDLE
),
9787 DUPLICATE_SAME_ACCESS
);
9789 DuplicateHandle (parent
,
9790 GetStdHandle (STD_OUTPUT_HANDLE
),
9795 DUPLICATE_SAME_ACCESS
);
9797 DuplicateHandle (parent
,
9798 GetStdHandle (STD_ERROR_HANDLE
),
9803 DUPLICATE_SAME_ACCESS
);
9809 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9810 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9812 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9815 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9816 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9818 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9821 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9822 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9824 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9828 /* unfortunately, atexit depends on implementation of malloc */
9829 /* atexit (term_ntproc); */
9832 /* Make sure we start with all signals unblocked. */
9833 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9834 signal (SIGABRT
, term_ntproc
);
9838 /* determine which drives are fixed, for GetCachedVolumeInformation */
9840 /* GetDriveType must have trailing backslash. */
9841 char drive
[] = "A:\\";
9843 /* Loop over all possible drive letters */
9844 while (*drive
<= 'Z')
9846 /* Record if this drive letter refers to a fixed drive. */
9847 fixed_drives
[DRIVE_INDEX (*drive
)] =
9848 (GetDriveType (drive
) == DRIVE_FIXED
);
9853 /* Reset the volume info cache. */
9854 volume_cache
= NULL
;
9859 shutdown_handler ensures that buffers' autosave files are
9860 up to date when the user logs off, or the system shuts down.
9863 shutdown_handler (DWORD type
)
9865 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9866 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9867 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9868 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9870 /* Shut down cleanly, making sure autosave files are up to date. */
9871 shut_down_emacs (0, Qnil
);
9874 /* Allow other handlers to handle this signal. */
9878 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9879 NT, return a handle to GDI32.DLL. */
9881 maybe_load_unicows_dll (void)
9883 if (os_subtype
== OS_9X
)
9885 HANDLE ret
= LoadLibrary ("Unicows.dll");
9888 /* These two functions are present on Windows 9X as stubs
9889 that always fail. We need the real implementations from
9890 UNICOWS.DLL, so we must call these functions through
9891 pointers, and assign the correct addresses to these
9892 pointers at program startup (see emacs.c, which calls
9893 this function early on). */
9894 pMultiByteToWideChar
=
9895 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9896 pWideCharToMultiByte
=
9897 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9898 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9905 button
= MessageBox (NULL
,
9906 "Emacs cannot load the UNICOWS.DLL library.\n"
9907 "This library is essential for using Emacs\n"
9908 "on this system. You need to install it.\n\n"
9909 "Emacs will exit when you click OK.",
9910 "Emacs cannot load UNICOWS.DLL",
9911 MB_ICONERROR
| MB_TASKMODAL
9912 | MB_SETFOREGROUND
| MB_OK
);
9923 /* On NT family of Windows, these two functions are always
9924 linked in, so we just assign their addresses to the 2
9925 pointers; no need for the LoadLibrary dance. */
9926 pMultiByteToWideChar
= MultiByteToWideChar
;
9927 pWideCharToMultiByte
= WideCharToMultiByte
;
9928 /* On NT 4.0, though, MB_ERR_INVALID_CHARS is not supported. */
9929 if (w32_major_version
< 5)
9930 multiByteToWideCharFlags
= 0;
9932 multiByteToWideCharFlags
= MB_ERR_INVALID_CHARS
;
9933 return LoadLibrary ("Gdi32.dll");
9938 globals_of_w32 is used to initialize those global variables that
9939 must always be initialized on startup even when the global variable
9940 initialized is non zero (see the function main in emacs.c).
9943 globals_of_w32 (void)
9945 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9947 get_process_times_fn
= (GetProcessTimes_Proc
)
9948 GetProcAddress (kernel32
, "GetProcessTimes");
9950 DEFSYM (QCloaded_from
, ":loaded-from");
9952 g_b_init_is_windows_9x
= 0;
9953 g_b_init_open_process_token
= 0;
9954 g_b_init_get_token_information
= 0;
9955 g_b_init_lookup_account_sid
= 0;
9956 g_b_init_get_sid_sub_authority
= 0;
9957 g_b_init_get_sid_sub_authority_count
= 0;
9958 g_b_init_get_security_info
= 0;
9959 g_b_init_get_file_security_w
= 0;
9960 g_b_init_get_file_security_a
= 0;
9961 g_b_init_get_security_descriptor_owner
= 0;
9962 g_b_init_get_security_descriptor_group
= 0;
9963 g_b_init_is_valid_sid
= 0;
9964 g_b_init_create_toolhelp32_snapshot
= 0;
9965 g_b_init_process32_first
= 0;
9966 g_b_init_process32_next
= 0;
9967 g_b_init_open_thread_token
= 0;
9968 g_b_init_impersonate_self
= 0;
9969 g_b_init_revert_to_self
= 0;
9970 g_b_init_get_process_memory_info
= 0;
9971 g_b_init_get_process_working_set_size
= 0;
9972 g_b_init_global_memory_status
= 0;
9973 g_b_init_global_memory_status_ex
= 0;
9974 g_b_init_equal_sid
= 0;
9975 g_b_init_copy_sid
= 0;
9976 g_b_init_get_length_sid
= 0;
9977 g_b_init_get_native_system_info
= 0;
9978 g_b_init_get_system_times
= 0;
9979 g_b_init_create_symbolic_link_w
= 0;
9980 g_b_init_create_symbolic_link_a
= 0;
9981 g_b_init_get_security_descriptor_dacl
= 0;
9982 g_b_init_convert_sd_to_sddl
= 0;
9983 g_b_init_convert_sddl_to_sd
= 0;
9984 g_b_init_is_valid_security_descriptor
= 0;
9985 g_b_init_set_file_security_w
= 0;
9986 g_b_init_set_file_security_a
= 0;
9987 g_b_init_set_named_security_info_w
= 0;
9988 g_b_init_set_named_security_info_a
= 0;
9989 g_b_init_get_adapters_info
= 0;
9990 g_b_init_reg_open_key_ex_w
= 0;
9991 g_b_init_reg_query_value_ex_w
= 0;
9992 g_b_init_expand_environment_strings_w
= 0;
9993 g_b_init_compare_string_w
= 0;
9994 g_b_init_debug_break_process
= 0;
9995 num_of_processors
= 0;
9996 /* The following sets a handler for shutdown notifications for
9997 console apps. This actually applies to Emacs in both console and
9998 GUI modes, since we had to fool windows into thinking emacs is a
9999 console application to get console mode to work. */
10000 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
10002 /* "None" is the default group name on standalone workstations. */
10003 strcpy (dflt_group_name
, "None");
10005 /* Reset, in case it has some value inherited from dump time. */
10006 w32_stat_get_owner_group
= 0;
10008 /* If w32_unicode_filenames is non-zero, we will be using Unicode
10009 (a.k.a. "wide") APIs to invoke functions that accept file
10011 if (is_windows_9x ())
10012 w32_unicode_filenames
= 0;
10014 w32_unicode_filenames
= 1;
10016 #ifdef HAVE_MODULES
10017 dynlib_reset_last_error ();
10020 w32_crypto_hprov
= (HCRYPTPROV
)0;
10023 /* For make-serial-process */
10025 serial_open (Lisp_Object port_obj
)
10027 char *port
= SSDATA (port_obj
);
10032 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
10033 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
10034 if (hnd
== INVALID_HANDLE_VALUE
)
10035 error ("Could not open %s", port
);
10036 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
10038 error ("Could not open %s", port
);
10042 error ("Could not create child process");
10044 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
10045 fd_info
[ fd
].hnd
= hnd
;
10046 fd_info
[ fd
].flags
|=
10047 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
10048 if (fd_info
[ fd
].cp
!= NULL
)
10050 error ("fd_info[fd = %d] is already in use", fd
);
10052 fd_info
[ fd
].cp
= cp
;
10053 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
10054 if (cp
->ovl_read
.hEvent
== NULL
)
10055 error ("Could not create read event");
10056 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
10057 if (cp
->ovl_write
.hEvent
== NULL
)
10058 error ("Could not create write event");
10063 /* For serial-process-configure */
10065 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
10067 Lisp_Object childp2
= Qnil
;
10068 Lisp_Object tem
= Qnil
;
10072 char summary
[4] = "???"; /* This usually becomes "8N1". */
10074 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
10075 error ("Not a serial process");
10076 hnd
= fd_info
[ p
->outfd
].hnd
;
10078 childp2
= Fcopy_sequence (p
->childp
);
10080 /* Initialize timeouts for blocking read and blocking write. */
10081 if (!GetCommTimeouts (hnd
, &ct
))
10082 error ("GetCommTimeouts() failed");
10083 ct
.ReadIntervalTimeout
= 0;
10084 ct
.ReadTotalTimeoutMultiplier
= 0;
10085 ct
.ReadTotalTimeoutConstant
= 0;
10086 ct
.WriteTotalTimeoutMultiplier
= 0;
10087 ct
.WriteTotalTimeoutConstant
= 0;
10088 if (!SetCommTimeouts (hnd
, &ct
))
10089 error ("SetCommTimeouts() failed");
10090 /* Read port attributes and prepare default configuration. */
10091 memset (&dcb
, 0, sizeof (dcb
));
10092 dcb
.DCBlength
= sizeof (DCB
);
10093 if (!GetCommState (hnd
, &dcb
))
10094 error ("GetCommState() failed");
10095 dcb
.fBinary
= TRUE
;
10097 dcb
.fAbortOnError
= FALSE
;
10098 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
10103 /* Configure speed. */
10104 if (!NILP (Fplist_member (contact
, QCspeed
)))
10105 tem
= Fplist_get (contact
, QCspeed
);
10107 tem
= Fplist_get (p
->childp
, QCspeed
);
10108 CHECK_NUMBER (tem
);
10109 dcb
.BaudRate
= XINT (tem
);
10110 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
10112 /* Configure bytesize. */
10113 if (!NILP (Fplist_member (contact
, QCbytesize
)))
10114 tem
= Fplist_get (contact
, QCbytesize
);
10116 tem
= Fplist_get (p
->childp
, QCbytesize
);
10118 tem
= make_number (8);
10119 CHECK_NUMBER (tem
);
10120 if (XINT (tem
) != 7 && XINT (tem
) != 8)
10121 error (":bytesize must be nil (8), 7, or 8");
10122 dcb
.ByteSize
= XINT (tem
);
10123 summary
[0] = XINT (tem
) + '0';
10124 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
10126 /* Configure parity. */
10127 if (!NILP (Fplist_member (contact
, QCparity
)))
10128 tem
= Fplist_get (contact
, QCparity
);
10130 tem
= Fplist_get (p
->childp
, QCparity
);
10131 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
10132 error (":parity must be nil (no parity), `even', or `odd'");
10133 dcb
.fParity
= FALSE
;
10134 dcb
.Parity
= NOPARITY
;
10135 dcb
.fErrorChar
= FALSE
;
10140 else if (EQ (tem
, Qeven
))
10143 dcb
.fParity
= TRUE
;
10144 dcb
.Parity
= EVENPARITY
;
10145 dcb
.fErrorChar
= TRUE
;
10147 else if (EQ (tem
, Qodd
))
10150 dcb
.fParity
= TRUE
;
10151 dcb
.Parity
= ODDPARITY
;
10152 dcb
.fErrorChar
= TRUE
;
10154 childp2
= Fplist_put (childp2
, QCparity
, tem
);
10156 /* Configure stopbits. */
10157 if (!NILP (Fplist_member (contact
, QCstopbits
)))
10158 tem
= Fplist_get (contact
, QCstopbits
);
10160 tem
= Fplist_get (p
->childp
, QCstopbits
);
10162 tem
= make_number (1);
10163 CHECK_NUMBER (tem
);
10164 if (XINT (tem
) != 1 && XINT (tem
) != 2)
10165 error (":stopbits must be nil (1 stopbit), 1, or 2");
10166 summary
[2] = XINT (tem
) + '0';
10167 if (XINT (tem
) == 1)
10168 dcb
.StopBits
= ONESTOPBIT
;
10169 else if (XINT (tem
) == 2)
10170 dcb
.StopBits
= TWOSTOPBITS
;
10171 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
10173 /* Configure flowcontrol. */
10174 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
10175 tem
= Fplist_get (contact
, QCflowcontrol
);
10177 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
10178 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
10179 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
10180 dcb
.fOutxCtsFlow
= FALSE
;
10181 dcb
.fOutxDsrFlow
= FALSE
;
10182 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
10183 dcb
.fDsrSensitivity
= FALSE
;
10184 dcb
.fTXContinueOnXoff
= FALSE
;
10187 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
10188 dcb
.XonChar
= 17; /* Control-Q */
10189 dcb
.XoffChar
= 19; /* Control-S */
10192 /* Already configured. */
10194 else if (EQ (tem
, Qhw
))
10196 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
10197 dcb
.fOutxCtsFlow
= TRUE
;
10199 else if (EQ (tem
, Qsw
))
10204 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
10206 /* Activate configuration. */
10207 if (!SetCommState (hnd
, &dcb
))
10208 error ("SetCommState() failed");
10210 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
10211 pset_childp (p
, childp2
);
10214 /* For make-pipe-process */
10216 register_aux_fd (int infd
)
10222 error ("Could not create child process");
10224 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
10226 if (fd_info
[ infd
].cp
!= NULL
)
10228 error ("fd_info[fd = %d] is already in use", infd
);
10230 fd_info
[ infd
].cp
= cp
;
10231 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
10237 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
10240 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
10241 int fd
= process
->infd
;
10243 n
= sys_read (fd
, (char*)buf
, sz
);
10250 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
10251 if (err
== EWOULDBLOCK
)
10254 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
10260 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
10262 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
10263 int fd
= process
->outfd
;
10264 ssize_t n
= sys_write (fd
, buf
, sz
);
10266 /* 0 or more bytes written means everything went fine. */
10270 /* Negative bytes written means we got an error in errno.
10271 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
10272 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
10273 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
10277 #endif /* HAVE_GNUTLS */