1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2015 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
10 (at 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 <http://www.gnu.org/licenses/>. */
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
24 #include <mingw_time.h>
25 #include <stddef.h> /* for offsetof */
28 #include <float.h> /* for DBL_EPSILON */
35 #include <time.h> /* must be before nt/inc/sys/time.h, for MinGW64 */
37 #include <sys/utime.h>
40 /* must include CRT headers *before* config.h */
43 #include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
70 #include "epaths.h" /* for PATH_EXEC */
75 /* MinGW64 defines these in its _mingw.h. */
76 #ifndef _ANONYMOUS_UNION
77 # define _ANONYMOUS_UNION
79 #ifndef _ANONYMOUS_STRUCT
80 # define _ANONYMOUS_STRUCT
83 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
84 use a different name to avoid compilation problems. */
85 typedef struct _MEMORY_STATUS_EX
{
88 DWORDLONG ullTotalPhys
;
89 DWORDLONG ullAvailPhys
;
90 DWORDLONG ullTotalPageFile
;
91 DWORDLONG ullAvailPageFile
;
92 DWORDLONG ullTotalVirtual
;
93 DWORDLONG ullAvailVirtual
;
94 DWORDLONG ullAvailExtendedVirtual
;
95 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
97 /* These are here so that GDB would know about these data types. This
98 allows to attach GDB to Emacs when a fatal exception is triggered
99 and Windows pops up the "application needs to be closed" dialog.
100 At that point, _gnu_exception_handler, the top-level exception
101 handler installed by the MinGW startup code, is somewhere on the
102 call-stack of the main thread, so going to that call frame and
103 looking at the argument to _gnu_exception_handler, which is a
104 PEXCEPTION_POINTERS pointer, can reveal the exception code
105 (excptr->ExceptionRecord->ExceptionCode) and the address where the
106 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
107 well as some additional information specific to the exception. */
108 PEXCEPTION_POINTERS excptr
;
109 PEXCEPTION_RECORD excprec
;
115 #include <tlhelp32.h>
120 #if _WIN32_WINNT < 0x0500
121 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
122 /* This either is not in psapi.h or guarded by higher value of
123 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
124 defines it in psapi.h */
125 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
127 DWORD PageFaultCount
;
128 SIZE_T PeakWorkingSetSize
;
129 SIZE_T WorkingSetSize
;
130 SIZE_T QuotaPeakPagedPoolUsage
;
131 SIZE_T QuotaPagedPoolUsage
;
132 SIZE_T QuotaPeakNonPagedPoolUsage
;
133 SIZE_T QuotaNonPagedPoolUsage
;
134 SIZE_T PagefileUsage
;
135 SIZE_T PeakPagefileUsage
;
137 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
141 #include <winioctl.h>
148 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
149 define them by hand if not already defined. */
150 #ifndef SDDL_REVISION_1
151 #define SDDL_REVISION_1 1
152 #endif /* SDDL_REVISION_1 */
154 #if defined(_MSC_VER) || defined(MINGW_W64)
155 /* MSVC and MinGW64 don't provide the definition of
156 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
157 which cannot be included because it triggers conflicts with other
158 Windows API headers. So we define it here by hand. */
160 typedef struct _REPARSE_DATA_BUFFER
{
162 USHORT ReparseDataLength
;
166 USHORT SubstituteNameOffset
;
167 USHORT SubstituteNameLength
;
168 USHORT PrintNameOffset
;
169 USHORT PrintNameLength
;
172 } SymbolicLinkReparseBuffer
;
174 USHORT SubstituteNameOffset
;
175 USHORT SubstituteNameLength
;
176 USHORT PrintNameOffset
;
177 USHORT PrintNameLength
;
179 } MountPointReparseBuffer
;
182 } GenericReparseBuffer
;
184 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
186 #ifndef FILE_DEVICE_FILE_SYSTEM
187 #define FILE_DEVICE_FILE_SYSTEM 9
189 #ifndef METHOD_BUFFERED
190 #define METHOD_BUFFERED 0
192 #ifndef FILE_ANY_ACCESS
193 #define FILE_ANY_ACCESS 0x00000000
196 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
198 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
199 #ifndef FSCTL_GET_REPARSE_POINT
200 #define FSCTL_GET_REPARSE_POINT \
201 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
205 /* TCP connection support. */
206 #include <sys/socket.h>
225 #include <iphlpapi.h> /* should be after winsock2.h */
227 #include <c-strcase.h>
231 #include "w32common.h"
232 #include "w32select.h"
233 #include "systime.h" /* for current_timespec, struct timespec */
234 #include "dispextern.h" /* for xstrcasecmp */
235 #include "coding.h" /* for Vlocale_coding_system */
237 #include "careadlinkat.h"
238 #include "allocator.h"
240 /* For Lisp_Process, serial_configure and serial_open. */
244 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
245 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
247 void globals_of_w32 (void);
248 static DWORD
get_rid (PSID
);
249 static int is_symlink (const char *);
250 static char * chase_symlinks (const char *);
251 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
252 static int restore_privilege (TOKEN_PRIVILEGES
*);
253 static BOOL WINAPI
revert_to_self (void);
255 static int sys_access (const char *, int);
256 extern void *e_malloc (size_t);
257 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
258 struct timespec
*, void *);
259 extern int sys_dup (int);
264 /* Initialization states.
266 WARNING: If you add any more such variables for additional APIs,
267 you MUST add initialization for them to globals_of_w32
268 below. This is because these variables might get set
269 to non-NULL values during dumping, but the dumped Emacs
270 cannot reuse those values, because it could be run on a
271 different version of the OS, where API addresses are
273 static BOOL g_b_init_is_windows_9x
;
274 static BOOL g_b_init_open_process_token
;
275 static BOOL g_b_init_get_token_information
;
276 static BOOL g_b_init_lookup_account_sid
;
277 static BOOL g_b_init_get_sid_sub_authority
;
278 static BOOL g_b_init_get_sid_sub_authority_count
;
279 static BOOL g_b_init_get_security_info
;
280 static BOOL g_b_init_get_file_security_w
;
281 static BOOL g_b_init_get_file_security_a
;
282 static BOOL g_b_init_get_security_descriptor_owner
;
283 static BOOL g_b_init_get_security_descriptor_group
;
284 static BOOL g_b_init_is_valid_sid
;
285 static BOOL g_b_init_create_toolhelp32_snapshot
;
286 static BOOL g_b_init_process32_first
;
287 static BOOL g_b_init_process32_next
;
288 static BOOL g_b_init_open_thread_token
;
289 static BOOL g_b_init_impersonate_self
;
290 static BOOL g_b_init_revert_to_self
;
291 static BOOL g_b_init_get_process_memory_info
;
292 static BOOL g_b_init_get_process_working_set_size
;
293 static BOOL g_b_init_global_memory_status
;
294 static BOOL g_b_init_global_memory_status_ex
;
295 static BOOL g_b_init_get_length_sid
;
296 static BOOL g_b_init_equal_sid
;
297 static BOOL g_b_init_copy_sid
;
298 static BOOL g_b_init_get_native_system_info
;
299 static BOOL g_b_init_get_system_times
;
300 static BOOL g_b_init_create_symbolic_link_w
;
301 static BOOL g_b_init_create_symbolic_link_a
;
302 static BOOL g_b_init_get_security_descriptor_dacl
;
303 static BOOL g_b_init_convert_sd_to_sddl
;
304 static BOOL g_b_init_convert_sddl_to_sd
;
305 static BOOL g_b_init_is_valid_security_descriptor
;
306 static BOOL g_b_init_set_file_security_w
;
307 static BOOL g_b_init_set_file_security_a
;
308 static BOOL g_b_init_set_named_security_info_w
;
309 static BOOL g_b_init_set_named_security_info_a
;
310 static BOOL g_b_init_get_adapters_info
;
312 BOOL g_b_init_compare_string_w
;
315 BEGIN: Wrapper functions around OpenProcessToken
316 and other functions in advapi32.dll that are only
317 supported in Windows NT / 2k / XP
319 /* ** Function pointer typedefs ** */
320 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
321 HANDLE ProcessHandle
,
323 PHANDLE TokenHandle
);
324 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
326 TOKEN_INFORMATION_CLASS TokenInformationClass
,
327 LPVOID TokenInformation
,
328 DWORD TokenInformationLength
,
329 PDWORD ReturnLength
);
330 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
331 HANDLE process_handle
,
332 LPFILETIME creation_time
,
333 LPFILETIME exit_time
,
334 LPFILETIME kernel_time
,
335 LPFILETIME user_time
);
337 GetProcessTimes_Proc get_process_times_fn
= NULL
;
340 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
342 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
344 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
345 LPCTSTR lpSystemName
,
350 LPDWORD cbDomainName
,
351 PSID_NAME_USE peUse
);
352 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
355 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
357 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
359 SE_OBJECT_TYPE ObjectType
,
360 SECURITY_INFORMATION SecurityInfo
,
365 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
366 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
368 SECURITY_INFORMATION RequestedInformation
,
369 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
371 LPDWORD lpnLengthNeeded
);
372 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
374 SECURITY_INFORMATION RequestedInformation
,
375 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
377 LPDWORD lpnLengthNeeded
);
378 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
380 SECURITY_INFORMATION SecurityInformation
,
381 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
382 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
384 SECURITY_INFORMATION SecurityInformation
,
385 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
386 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
387 LPCWSTR lpObjectName
,
388 SE_OBJECT_TYPE ObjectType
,
389 SECURITY_INFORMATION SecurityInformation
,
394 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
396 SE_OBJECT_TYPE ObjectType
,
397 SECURITY_INFORMATION SecurityInformation
,
402 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
403 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
405 LPBOOL lpbOwnerDefaulted
);
406 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
407 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
409 LPBOOL lpbGroupDefaulted
);
410 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
411 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
412 LPBOOL lpbDaclPresent
,
414 LPBOOL lpbDaclDefaulted
);
415 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
417 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
419 DWORD th32ProcessID
);
420 typedef BOOL (WINAPI
* Process32First_Proc
) (
422 LPPROCESSENTRY32 lppe
);
423 typedef BOOL (WINAPI
* Process32Next_Proc
) (
425 LPPROCESSENTRY32 lppe
);
426 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
430 PHANDLE TokenHandle
);
431 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
432 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
433 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
434 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
436 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
438 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
440 PSIZE_T lpMinimumWorkingSetSize
,
441 PSIZE_T lpMaximumWorkingSetSize
);
442 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
443 LPMEMORYSTATUS lpBuffer
);
444 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
445 LPMEMORY_STATUS_EX lpBuffer
);
446 typedef BOOL (WINAPI
* CopySid_Proc
) (
447 DWORD nDestinationSidLength
,
448 PSID pDestinationSid
,
450 typedef BOOL (WINAPI
* EqualSid_Proc
) (
453 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
455 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
456 LPSYSTEM_INFO lpSystemInfo
);
457 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
458 LPFILETIME lpIdleTime
,
459 LPFILETIME lpKernelTime
,
460 LPFILETIME lpUserTime
);
461 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
462 LPCWSTR lpSymlinkFileName
,
463 LPCWSTR lpTargetFileName
,
465 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
466 LPCSTR lpSymlinkFileName
,
467 LPCSTR lpTargetFileName
,
469 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
470 LPCTSTR StringSecurityDescriptor
,
471 DWORD StringSDRevision
,
472 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
473 PULONG SecurityDescriptorSize
);
474 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
475 PSECURITY_DESCRIPTOR SecurityDescriptor
,
476 DWORD RequestedStringSDRevision
,
477 SECURITY_INFORMATION SecurityInformation
,
478 LPTSTR
*StringSecurityDescriptor
,
479 PULONG StringSecurityDescriptorLen
);
480 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
481 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
482 PIP_ADAPTER_INFO pAdapterInfo
,
485 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
486 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
488 /* ** A utility function ** */
492 static BOOL s_b_ret
= 0;
493 OSVERSIONINFO os_ver
;
494 if (g_b_init_is_windows_9x
== 0)
496 g_b_init_is_windows_9x
= 1;
497 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
498 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
499 if (GetVersionEx (&os_ver
))
501 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
507 static Lisp_Object
ltime (ULONGLONG
);
509 /* Get total user and system times for get-internal-run-time.
510 Returns a list of integers if the times are provided by the OS
511 (NT derivatives), otherwise it returns the result of current-time. */
513 w32_get_internal_run_time (void)
515 if (get_process_times_fn
)
517 FILETIME create
, exit
, kernel
, user
;
518 HANDLE proc
= GetCurrentProcess ();
519 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
521 LARGE_INTEGER user_int
, kernel_int
, total
;
522 user_int
.LowPart
= user
.dwLowDateTime
;
523 user_int
.HighPart
= user
.dwHighDateTime
;
524 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
525 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
526 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
527 return ltime (total
.QuadPart
);
531 return Fcurrent_time ();
534 /* ** The wrapper functions ** */
537 open_process_token (HANDLE ProcessHandle
,
541 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
542 HMODULE hm_advapi32
= NULL
;
543 if (is_windows_9x () == TRUE
)
547 if (g_b_init_open_process_token
== 0)
549 g_b_init_open_process_token
= 1;
550 hm_advapi32
= LoadLibrary ("Advapi32.dll");
551 s_pfn_Open_Process_Token
=
552 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
554 if (s_pfn_Open_Process_Token
== NULL
)
559 s_pfn_Open_Process_Token (
567 get_token_information (HANDLE TokenHandle
,
568 TOKEN_INFORMATION_CLASS TokenInformationClass
,
569 LPVOID TokenInformation
,
570 DWORD TokenInformationLength
,
573 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
574 HMODULE hm_advapi32
= NULL
;
575 if (is_windows_9x () == TRUE
)
579 if (g_b_init_get_token_information
== 0)
581 g_b_init_get_token_information
= 1;
582 hm_advapi32
= LoadLibrary ("Advapi32.dll");
583 s_pfn_Get_Token_Information
=
584 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
586 if (s_pfn_Get_Token_Information
== NULL
)
591 s_pfn_Get_Token_Information (
593 TokenInformationClass
,
595 TokenInformationLength
,
601 lookup_account_sid (LPCTSTR lpSystemName
,
606 LPDWORD cbDomainName
,
609 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
610 HMODULE hm_advapi32
= NULL
;
611 if (is_windows_9x () == TRUE
)
615 if (g_b_init_lookup_account_sid
== 0)
617 g_b_init_lookup_account_sid
= 1;
618 hm_advapi32
= LoadLibrary ("Advapi32.dll");
619 s_pfn_Lookup_Account_Sid
=
620 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
622 if (s_pfn_Lookup_Account_Sid
== NULL
)
627 s_pfn_Lookup_Account_Sid (
639 get_sid_sub_authority (PSID pSid
, DWORD n
)
641 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
642 static DWORD zero
= 0U;
643 HMODULE hm_advapi32
= NULL
;
644 if (is_windows_9x () == TRUE
)
648 if (g_b_init_get_sid_sub_authority
== 0)
650 g_b_init_get_sid_sub_authority
= 1;
651 hm_advapi32
= LoadLibrary ("Advapi32.dll");
652 s_pfn_Get_Sid_Sub_Authority
=
653 (GetSidSubAuthority_Proc
) GetProcAddress (
654 hm_advapi32
, "GetSidSubAuthority");
656 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
660 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
664 get_sid_sub_authority_count (PSID pSid
)
666 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
667 static UCHAR zero
= 0U;
668 HMODULE hm_advapi32
= NULL
;
669 if (is_windows_9x () == TRUE
)
673 if (g_b_init_get_sid_sub_authority_count
== 0)
675 g_b_init_get_sid_sub_authority_count
= 1;
676 hm_advapi32
= LoadLibrary ("Advapi32.dll");
677 s_pfn_Get_Sid_Sub_Authority_Count
=
678 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
679 hm_advapi32
, "GetSidSubAuthorityCount");
681 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
685 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
689 get_security_info (HANDLE handle
,
690 SE_OBJECT_TYPE ObjectType
,
691 SECURITY_INFORMATION SecurityInfo
,
696 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
698 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
699 HMODULE hm_advapi32
= NULL
;
700 if (is_windows_9x () == TRUE
)
704 if (g_b_init_get_security_info
== 0)
706 g_b_init_get_security_info
= 1;
707 hm_advapi32
= LoadLibrary ("Advapi32.dll");
708 s_pfn_Get_Security_Info
=
709 (GetSecurityInfo_Proc
) GetProcAddress (
710 hm_advapi32
, "GetSecurityInfo");
712 if (s_pfn_Get_Security_Info
== NULL
)
716 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
717 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
718 ppSecurityDescriptor
));
722 get_file_security (const char *lpFileName
,
723 SECURITY_INFORMATION RequestedInformation
,
724 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
726 LPDWORD lpnLengthNeeded
)
728 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
729 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
730 HMODULE hm_advapi32
= NULL
;
731 if (is_windows_9x () == TRUE
)
736 if (w32_unicode_filenames
)
738 wchar_t filename_w
[MAX_PATH
];
740 if (g_b_init_get_file_security_w
== 0)
742 g_b_init_get_file_security_w
= 1;
743 hm_advapi32
= LoadLibrary ("Advapi32.dll");
744 s_pfn_Get_File_SecurityW
=
745 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
748 if (s_pfn_Get_File_SecurityW
== NULL
)
753 filename_to_utf16 (lpFileName
, filename_w
);
754 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
755 pSecurityDescriptor
, nLength
,
760 char filename_a
[MAX_PATH
];
762 if (g_b_init_get_file_security_a
== 0)
764 g_b_init_get_file_security_a
= 1;
765 hm_advapi32
= LoadLibrary ("Advapi32.dll");
766 s_pfn_Get_File_SecurityA
=
767 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
770 if (s_pfn_Get_File_SecurityA
== NULL
)
775 filename_to_ansi (lpFileName
, filename_a
);
776 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
777 pSecurityDescriptor
, nLength
,
783 set_file_security (const char *lpFileName
,
784 SECURITY_INFORMATION SecurityInformation
,
785 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
787 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
788 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
789 HMODULE hm_advapi32
= NULL
;
790 if (is_windows_9x () == TRUE
)
795 if (w32_unicode_filenames
)
797 wchar_t filename_w
[MAX_PATH
];
799 if (g_b_init_set_file_security_w
== 0)
801 g_b_init_set_file_security_w
= 1;
802 hm_advapi32
= LoadLibrary ("Advapi32.dll");
803 s_pfn_Set_File_SecurityW
=
804 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
807 if (s_pfn_Set_File_SecurityW
== NULL
)
812 filename_to_utf16 (lpFileName
, filename_w
);
813 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
814 pSecurityDescriptor
));
818 char filename_a
[MAX_PATH
];
820 if (g_b_init_set_file_security_a
== 0)
822 g_b_init_set_file_security_a
= 1;
823 hm_advapi32
= LoadLibrary ("Advapi32.dll");
824 s_pfn_Set_File_SecurityA
=
825 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
828 if (s_pfn_Set_File_SecurityA
== NULL
)
833 filename_to_ansi (lpFileName
, filename_a
);
834 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
835 pSecurityDescriptor
));
840 set_named_security_info (LPCTSTR lpObjectName
,
841 SE_OBJECT_TYPE ObjectType
,
842 SECURITY_INFORMATION SecurityInformation
,
848 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
849 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
850 HMODULE hm_advapi32
= NULL
;
851 if (is_windows_9x () == TRUE
)
856 if (w32_unicode_filenames
)
858 wchar_t filename_w
[MAX_PATH
];
860 if (g_b_init_set_named_security_info_w
== 0)
862 g_b_init_set_named_security_info_w
= 1;
863 hm_advapi32
= LoadLibrary ("Advapi32.dll");
864 s_pfn_Set_Named_Security_InfoW
=
865 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
866 "SetNamedSecurityInfoW");
868 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
873 filename_to_utf16 (lpObjectName
, filename_w
);
874 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
875 SecurityInformation
, psidOwner
,
876 psidGroup
, pDacl
, pSacl
));
880 char filename_a
[MAX_PATH
];
882 if (g_b_init_set_named_security_info_a
== 0)
884 g_b_init_set_named_security_info_a
= 1;
885 hm_advapi32
= LoadLibrary ("Advapi32.dll");
886 s_pfn_Set_Named_Security_InfoA
=
887 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
888 "SetNamedSecurityInfoA");
890 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
895 filename_to_ansi (lpObjectName
, filename_a
);
896 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
897 SecurityInformation
, psidOwner
,
898 psidGroup
, pDacl
, pSacl
));
903 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
905 LPBOOL lpbOwnerDefaulted
)
907 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
908 HMODULE hm_advapi32
= NULL
;
909 if (is_windows_9x () == TRUE
)
914 if (g_b_init_get_security_descriptor_owner
== 0)
916 g_b_init_get_security_descriptor_owner
= 1;
917 hm_advapi32
= LoadLibrary ("Advapi32.dll");
918 s_pfn_Get_Security_Descriptor_Owner
=
919 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
920 hm_advapi32
, "GetSecurityDescriptorOwner");
922 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
927 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
932 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
934 LPBOOL lpbGroupDefaulted
)
936 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
937 HMODULE hm_advapi32
= NULL
;
938 if (is_windows_9x () == TRUE
)
943 if (g_b_init_get_security_descriptor_group
== 0)
945 g_b_init_get_security_descriptor_group
= 1;
946 hm_advapi32
= LoadLibrary ("Advapi32.dll");
947 s_pfn_Get_Security_Descriptor_Group
=
948 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
949 hm_advapi32
, "GetSecurityDescriptorGroup");
951 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
956 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
961 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
962 LPBOOL lpbDaclPresent
,
964 LPBOOL lpbDaclDefaulted
)
966 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
967 HMODULE hm_advapi32
= NULL
;
968 if (is_windows_9x () == TRUE
)
973 if (g_b_init_get_security_descriptor_dacl
== 0)
975 g_b_init_get_security_descriptor_dacl
= 1;
976 hm_advapi32
= LoadLibrary ("Advapi32.dll");
977 s_pfn_Get_Security_Descriptor_Dacl
=
978 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
979 hm_advapi32
, "GetSecurityDescriptorDacl");
981 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
986 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
987 lpbDaclPresent
, pDacl
,
992 is_valid_sid (PSID sid
)
994 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
995 HMODULE hm_advapi32
= NULL
;
996 if (is_windows_9x () == TRUE
)
1000 if (g_b_init_is_valid_sid
== 0)
1002 g_b_init_is_valid_sid
= 1;
1003 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1004 s_pfn_Is_Valid_Sid
=
1005 (IsValidSid_Proc
) GetProcAddress (
1006 hm_advapi32
, "IsValidSid");
1008 if (s_pfn_Is_Valid_Sid
== NULL
)
1012 return (s_pfn_Is_Valid_Sid (sid
));
1016 equal_sid (PSID sid1
, PSID sid2
)
1018 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1019 HMODULE hm_advapi32
= NULL
;
1020 if (is_windows_9x () == TRUE
)
1024 if (g_b_init_equal_sid
== 0)
1026 g_b_init_equal_sid
= 1;
1027 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1029 (EqualSid_Proc
) GetProcAddress (
1030 hm_advapi32
, "EqualSid");
1032 if (s_pfn_Equal_Sid
== NULL
)
1036 return (s_pfn_Equal_Sid (sid1
, sid2
));
1040 get_length_sid (PSID sid
)
1042 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1043 HMODULE hm_advapi32
= NULL
;
1044 if (is_windows_9x () == TRUE
)
1048 if (g_b_init_get_length_sid
== 0)
1050 g_b_init_get_length_sid
= 1;
1051 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1052 s_pfn_Get_Length_Sid
=
1053 (GetLengthSid_Proc
) GetProcAddress (
1054 hm_advapi32
, "GetLengthSid");
1056 if (s_pfn_Get_Length_Sid
== NULL
)
1060 return (s_pfn_Get_Length_Sid (sid
));
1064 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1066 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1067 HMODULE hm_advapi32
= NULL
;
1068 if (is_windows_9x () == TRUE
)
1072 if (g_b_init_copy_sid
== 0)
1074 g_b_init_copy_sid
= 1;
1075 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1077 (CopySid_Proc
) GetProcAddress (
1078 hm_advapi32
, "CopySid");
1080 if (s_pfn_Copy_Sid
== NULL
)
1084 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1088 END: Wrapper functions around OpenProcessToken
1089 and other functions in advapi32.dll that are only
1090 supported in Windows NT / 2k / XP
1094 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1096 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1097 if (is_windows_9x () != TRUE
)
1099 if (g_b_init_get_native_system_info
== 0)
1101 g_b_init_get_native_system_info
= 1;
1102 s_pfn_Get_Native_System_Info
=
1103 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1104 "GetNativeSystemInfo");
1106 if (s_pfn_Get_Native_System_Info
!= NULL
)
1107 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1110 lpSystemInfo
->dwNumberOfProcessors
= -1;
1114 get_system_times (LPFILETIME lpIdleTime
,
1115 LPFILETIME lpKernelTime
,
1116 LPFILETIME lpUserTime
)
1118 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1119 if (is_windows_9x () == TRUE
)
1123 if (g_b_init_get_system_times
== 0)
1125 g_b_init_get_system_times
= 1;
1126 s_pfn_Get_System_times
=
1127 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1130 if (s_pfn_Get_System_times
== NULL
)
1132 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1135 static BOOLEAN WINAPI
1136 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1137 LPCSTR lpTargetFileName
,
1140 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1141 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1144 if (is_windows_9x () == TRUE
)
1149 if (w32_unicode_filenames
)
1151 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1153 if (g_b_init_create_symbolic_link_w
== 0)
1155 g_b_init_create_symbolic_link_w
= 1;
1156 s_pfn_Create_Symbolic_LinkW
=
1157 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1158 "CreateSymbolicLinkW");
1160 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1166 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1167 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1168 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1169 /* If we were denied creation of the symlink, try again after
1170 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1173 TOKEN_PRIVILEGES priv_current
;
1175 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1178 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1179 restore_privilege (&priv_current
);
1186 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1188 if (g_b_init_create_symbolic_link_a
== 0)
1190 g_b_init_create_symbolic_link_a
= 1;
1191 s_pfn_Create_Symbolic_LinkA
=
1192 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1193 "CreateSymbolicLinkA");
1195 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1201 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1202 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1203 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1204 /* If we were denied creation of the symlink, try again after
1205 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1208 TOKEN_PRIVILEGES priv_current
;
1210 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1213 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1214 restore_privilege (&priv_current
);
1223 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1225 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1227 if (is_windows_9x () == TRUE
)
1233 if (g_b_init_is_valid_security_descriptor
== 0)
1235 g_b_init_is_valid_security_descriptor
= 1;
1236 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1237 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1238 "IsValidSecurityDescriptor");
1240 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1246 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1250 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1251 DWORD RequestedStringSDRevision
,
1252 SECURITY_INFORMATION SecurityInformation
,
1253 LPTSTR
*StringSecurityDescriptor
,
1254 PULONG StringSecurityDescriptorLen
)
1256 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1259 if (is_windows_9x () == TRUE
)
1265 if (g_b_init_convert_sd_to_sddl
== 0)
1267 g_b_init_convert_sd_to_sddl
= 1;
1269 s_pfn_Convert_SD_To_SDDL
=
1270 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1271 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1273 s_pfn_Convert_SD_To_SDDL
=
1274 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1275 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1278 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1284 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1285 RequestedStringSDRevision
,
1286 SecurityInformation
,
1287 StringSecurityDescriptor
,
1288 StringSecurityDescriptorLen
);
1294 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1295 DWORD StringSDRevision
,
1296 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1297 PULONG SecurityDescriptorSize
)
1299 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1302 if (is_windows_9x () == TRUE
)
1308 if (g_b_init_convert_sddl_to_sd
== 0)
1310 g_b_init_convert_sddl_to_sd
= 1;
1312 s_pfn_Convert_SDDL_To_SD
=
1313 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1314 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1316 s_pfn_Convert_SDDL_To_SD
=
1317 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1318 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1321 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1327 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1330 SecurityDescriptorSize
);
1336 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1338 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1339 HMODULE hm_iphlpapi
= NULL
;
1341 if (is_windows_9x () == TRUE
)
1342 return ERROR_NOT_SUPPORTED
;
1344 if (g_b_init_get_adapters_info
== 0)
1346 g_b_init_get_adapters_info
= 1;
1347 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1349 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1350 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1352 if (s_pfn_Get_Adapters_Info
== NULL
)
1353 return ERROR_NOT_SUPPORTED
;
1354 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1359 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1360 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1362 This is called from alloc.c:valid_pointer_p. */
1364 w32_valid_pointer_p (void *p
, int size
)
1367 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1371 unsigned char *buf
= alloca (size
);
1372 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1383 /* Here's an overview of how the Windows build supports file names
1384 that cannot be encoded by the current system codepage.
1386 From the POV of Lisp and layers of C code above the functions here,
1387 Emacs on Windows pretends that its file names are encoded in UTF-8;
1388 see encode_file and decode_file on coding.c. Any file name that is
1389 passed as a unibyte string to C functions defined here is assumed
1390 to be in UTF-8 encoding. Any file name returned by functions
1391 defined here must be in UTF-8 encoding, with only a few exceptions
1392 reserved for a couple of special cases. (Be sure to use
1393 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1394 as they can be much longer than MAX_PATH!)
1396 The UTF-8 encoded file names cannot be passed to system APIs, as
1397 Windows does not support that. Therefore, they are converted
1398 either to UTF-16 or to the ANSI codepage, depending on the value of
1399 w32-unicode-filenames, before calling any system APIs or CRT library
1400 functions. The default value of that variable is determined by the
1401 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1402 user can change that default (although I don't see why would she
1405 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1406 filename_from_utf16, and filename_from_ansi, are the workhorses of
1407 these conversions. They rely on Windows native APIs
1408 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1409 functions from coding.c here, because they allocate memory, which
1410 is a bad idea on the level of libc, which is what the functions
1411 here emulate. (If you worry about performance due to constant
1412 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1413 it was measured to take only a few microseconds on a not-so-fast
1414 machine, and second, that's exactly what the ANSI APIs we used
1415 before did anyway, because they are just thin wrappers around the
1418 The variables file-name-coding-system and default-file-name-coding-system
1419 still exist, but are actually used only when a file name needs to
1420 be converted to the ANSI codepage. This happens all the time when
1421 w32-unicode-filenames is nil, but can also happen from time to time
1422 when it is t. Otherwise, these variables have no effect on file-name
1423 encoding when w32-unicode-filenames is t; this is similar to
1424 selection-coding-system.
1426 This arrangement works very well, but it has a few gotchas and
1429 . Lisp code that encodes or decodes file names manually should
1430 normally use 'utf-8' as the coding-system on Windows,
1431 disregarding file-name-coding-system. This is a somewhat
1432 unpleasant consequence, but it cannot be avoided. Fortunately,
1433 very few Lisp packages need to do that.
1435 More generally, passing to library functions (e.g., fopen or
1436 opendir) file names already encoded in the ANSI codepage is
1437 explicitly *verboten*, as all those functions, as shadowed and
1438 emulated here, assume they will receive UTF-8 encoded file names.
1440 For the same reasons, no CRT function or Win32 API can be called
1441 directly in Emacs sources, without either converting the file
1442 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1443 some shadowing function defined here.
1445 . Environment variables stored in Vprocess_environment are encoded
1446 in the ANSI codepage, so if getenv/egetenv is used for a variable
1447 whose value is a file name or a list of directories, it needs to
1448 be converted to UTF-8, before it is used as argument to functions
1449 or decoded into a Lisp string.
1451 . File names passed to external libraries, like the image libraries
1452 and GnuTLS, need special handling. These libraries generally
1453 don't support UTF-16 or UTF-8 file names, so they must get file
1454 names encoded in the ANSI codepage. To facilitate using these
1455 libraries with file names that are not encodable in the ANSI
1456 codepage, use the function ansi_encode_filename, which will try
1457 to use the short 8+3 alias of a file name if that file name is
1458 not encodable in the ANSI codepage. See image.c and gnutls.c for
1459 examples of how this should be done.
1461 . Running subprocesses in non-ASCII directories and with non-ASCII
1462 file arguments is limited to the current codepage (even though
1463 Emacs is perfectly capable of finding an executable program file
1464 in a directory whose name cannot be encoded in the current
1465 codepage). This is because the command-line arguments are
1466 encoded _before_ they get to the w32-specific level, and the
1467 encoding is not known in advance (it doesn't have to be the
1468 current ANSI codepage), so w32proc.c functions cannot re-encode
1469 them in UTF-16. This should be fixed, but will also require
1470 changes in cmdproxy. The current limitation is not terribly bad
1471 anyway, since very few, if any, Windows console programs that are
1472 likely to be invoked by Emacs support UTF-16 encoded command
1475 . For similar reasons, server.el and emacsclient are also limited
1476 to the current ANSI codepage for now.
1478 . Emacs itself can only handle command-line arguments encoded in
1479 the current codepage.
1481 . Turning on w32-unicode-filename on Windows 9X (if it at all
1482 works) requires UNICOWS.DLL, which is thus a requirement even in
1483 non-GUI sessions, something the we previously avoided. */
1487 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1488 codepage defined by file-name-coding-system. */
1490 /* Current codepage for encoding file names. */
1491 static int file_name_codepage
;
1493 /* Produce a Windows ANSI codepage suitable for encoding file names.
1494 Return the information about that codepage in CP_INFO. */
1496 codepage_for_filenames (CPINFO
*cp_info
)
1498 /* A simple cache to avoid calling GetCPInfo every time we need to
1499 encode/decode a file name. The file-name encoding is not
1500 supposed to be changed too frequently, if ever. */
1501 static Lisp_Object last_file_name_encoding
;
1503 Lisp_Object current_encoding
;
1505 current_encoding
= Vfile_name_coding_system
;
1506 if (NILP (current_encoding
))
1507 current_encoding
= Vdefault_file_name_coding_system
;
1509 if (!EQ (last_file_name_encoding
, current_encoding
))
1511 /* Default to the current ANSI codepage. */
1512 file_name_codepage
= w32_ansi_code_page
;
1514 if (NILP (current_encoding
))
1516 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1517 char *cp
= NULL
, *end
;
1520 if (strncmp (cpname
, "cp", 2) == 0)
1522 else if (strncmp (cpname
, "windows-", 8) == 0)
1528 cpnum
= strtol (cp
, &end
, 10);
1529 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1530 file_name_codepage
= cpnum
;
1534 if (!file_name_codepage
)
1535 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1537 if (!GetCPInfo (file_name_codepage
, &cp
))
1539 file_name_codepage
= CP_ACP
;
1540 if (!GetCPInfo (file_name_codepage
, &cp
))
1547 return file_name_codepage
;
1551 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1553 int result
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1558 DWORD err
= GetLastError ();
1562 case ERROR_INVALID_FLAGS
:
1563 case ERROR_INVALID_PARAMETER
:
1566 case ERROR_INSUFFICIENT_BUFFER
:
1567 case ERROR_NO_UNICODE_TRANSLATION
:
1578 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1580 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1581 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1585 DWORD err
= GetLastError ();
1589 case ERROR_INVALID_FLAGS
:
1590 case ERROR_INVALID_PARAMETER
:
1593 case ERROR_INSUFFICIENT_BUFFER
:
1594 case ERROR_NO_UNICODE_TRANSLATION
:
1605 filename_to_ansi (const char *fn_in
, char *fn_out
)
1607 wchar_t fn_utf16
[MAX_PATH
];
1609 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1612 int codepage
= codepage_for_filenames (NULL
);
1614 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1615 fn_out
, MAX_PATH
, NULL
, NULL
);
1618 DWORD err
= GetLastError ();
1622 case ERROR_INVALID_FLAGS
:
1623 case ERROR_INVALID_PARAMETER
:
1626 case ERROR_INSUFFICIENT_BUFFER
:
1627 case ERROR_NO_UNICODE_TRANSLATION
:
1640 filename_from_ansi (const char *fn_in
, char *fn_out
)
1642 wchar_t fn_utf16
[MAX_PATH
];
1643 int codepage
= codepage_for_filenames (NULL
);
1644 int result
= pMultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1645 fn_utf16
, MAX_PATH
);
1649 DWORD err
= GetLastError ();
1653 case ERROR_INVALID_FLAGS
:
1654 case ERROR_INVALID_PARAMETER
:
1657 case ERROR_INSUFFICIENT_BUFFER
:
1658 case ERROR_NO_UNICODE_TRANSLATION
:
1665 return filename_from_utf16 (fn_utf16
, fn_out
);
1670 /* The directory where we started, in UTF-8. */
1671 static char startup_dir
[MAX_UTF8_PATH
];
1673 /* Get the current working directory. */
1675 getcwd (char *dir
, int dirsize
)
1682 if (dirsize
<= strlen (startup_dir
))
1688 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1692 /* Emacs doesn't actually change directory itself, it stays in the
1693 same directory where it was started. */
1694 strcpy (dir
, startup_dir
);
1699 /* Emulate getloadavg. */
1701 struct load_sample
{
1708 /* Number of processors on this machine. */
1709 static unsigned num_of_processors
;
1711 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1712 static struct load_sample samples
[16*60];
1713 static int first_idx
= -1, last_idx
= -1;
1714 static int max_idx
= ARRAYELTS (samples
);
1719 int next_idx
= from
+ 1;
1721 if (next_idx
>= max_idx
)
1730 int prev_idx
= from
- 1;
1733 prev_idx
= max_idx
- 1;
1739 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1741 SYSTEM_INFO sysinfo
;
1742 FILETIME ft_idle
, ft_user
, ft_kernel
;
1744 /* Initialize the number of processors on this machine. */
1745 if (num_of_processors
<= 0)
1747 get_native_system_info (&sysinfo
);
1748 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1749 if (num_of_processors
<= 0)
1751 GetSystemInfo (&sysinfo
);
1752 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1754 if (num_of_processors
<= 0)
1755 num_of_processors
= 1;
1758 /* TODO: Take into account threads that are ready to run, by
1759 sampling the "\System\Processor Queue Length" performance
1760 counter. The code below accounts only for threads that are
1761 actually running. */
1763 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1765 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1767 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1768 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1769 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1770 *idle
= uidle
.QuadPart
;
1771 *kernel
= ukernel
.QuadPart
;
1772 *user
= uuser
.QuadPart
;
1782 /* Produce the load average for a given time interval, using the
1783 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1784 1-minute, 5-minute, or 15-minute average, respectively. */
1788 double retval
= -1.0;
1791 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1792 time_t now
= samples
[last_idx
].sample_time
;
1794 if (first_idx
!= last_idx
)
1796 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1798 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1799 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1802 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1803 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1804 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1806 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1809 if (idx
== first_idx
)
1818 getloadavg (double loadavg
[], int nelem
)
1821 ULONGLONG idle
, kernel
, user
;
1822 time_t now
= time (NULL
);
1824 /* If system time jumped back for some reason, delete all samples
1825 whose time is later than the current wall-clock time. This
1826 prevents load average figures from becoming frozen for prolonged
1827 periods of time, when system time is reset backwards. */
1830 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1832 if (last_idx
== first_idx
)
1834 first_idx
= last_idx
= -1;
1837 last_idx
= buf_prev (last_idx
);
1841 /* Store another sample. We ignore samples that are less than 1 sec
1844 || (difftime (now
, samples
[last_idx
].sample_time
)
1845 >= 1.0 - 2*DBL_EPSILON
*now
))
1847 sample_system_load (&idle
, &kernel
, &user
);
1848 last_idx
= buf_next (last_idx
);
1849 samples
[last_idx
].sample_time
= now
;
1850 samples
[last_idx
].idle
= idle
;
1851 samples
[last_idx
].kernel
= kernel
;
1852 samples
[last_idx
].user
= user
;
1853 /* If the buffer has more that 15 min worth of samples, discard
1855 if (first_idx
== -1)
1856 first_idx
= last_idx
;
1857 while (first_idx
!= last_idx
1858 && (difftime (now
, samples
[first_idx
].sample_time
)
1859 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1860 first_idx
= buf_next (first_idx
);
1863 for (elem
= 0; elem
< nelem
; elem
++)
1865 double avg
= getavg (elem
);
1869 loadavg
[elem
] = avg
;
1875 /* Emulate getpwuid, getpwnam and others. */
1877 #define PASSWD_FIELD_SIZE 256
1879 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1880 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1881 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1882 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1883 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1885 static struct passwd dflt_passwd
=
1897 static char dflt_group_name
[GNLEN
+1];
1899 static struct group dflt_group
=
1901 /* When group information is not available, we return this as the
1902 group for all files. */
1910 return dflt_passwd
.pw_uid
;
1916 /* I could imagine arguing for checking to see whether the user is
1917 in the Administrators group and returning a UID of 0 for that
1918 case, but I don't know how wise that would be in the long run. */
1925 return dflt_passwd
.pw_gid
;
1935 getpwuid (unsigned uid
)
1937 if (uid
== dflt_passwd
.pw_uid
)
1938 return &dflt_passwd
;
1943 getgrgid (gid_t gid
)
1949 getpwnam (char *name
)
1953 pw
= getpwuid (getuid ());
1957 if (xstrcasecmp (name
, pw
->pw_name
))
1964 init_user_info (void)
1966 /* Find the user's real name by opening the process token and
1967 looking up the name associated with the user-sid in that token.
1969 Use the relative portion of the identifier authority value from
1970 the user-sid as the user id value (same for group id using the
1971 primary group sid from the process token). */
1973 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1974 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1975 DWORD glength
= sizeof (gname
);
1976 HANDLE token
= NULL
;
1977 SID_NAME_USE user_type
;
1978 unsigned char *buf
= NULL
;
1980 TOKEN_USER user_token
;
1981 TOKEN_PRIMARY_GROUP group_token
;
1984 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1987 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1988 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1990 buf
= xmalloc (blen
);
1991 result
= get_token_information (token
, TokenUser
,
1992 (LPVOID
)buf
, blen
, &needed
);
1995 memcpy (&user_token
, buf
, sizeof (user_token
));
1996 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1998 domain
, &dlength
, &user_type
);
2006 strcpy (dflt_passwd
.pw_name
, uname
);
2007 /* Determine a reasonable uid value. */
2008 if (xstrcasecmp ("administrator", uname
) == 0)
2010 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2011 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2015 /* Use the last sub-authority value of the RID, the relative
2016 portion of the SID, as user/group ID. */
2017 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2019 /* Get group id and name. */
2020 result
= get_token_information (token
, TokenPrimaryGroup
,
2021 (LPVOID
)buf
, blen
, &needed
);
2022 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2024 buf
= xrealloc (buf
, blen
= needed
);
2025 result
= get_token_information (token
, TokenPrimaryGroup
,
2026 (LPVOID
)buf
, blen
, &needed
);
2030 memcpy (&group_token
, buf
, sizeof (group_token
));
2031 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2032 dlength
= sizeof (domain
);
2033 /* If we can get at the real Primary Group name, use that.
2034 Otherwise, the default group name was already set to
2035 "None" in globals_of_w32. */
2036 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2037 gname
, &glength
, NULL
, &dlength
,
2039 strcpy (dflt_group_name
, gname
);
2042 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2045 /* If security calls are not supported (presumably because we
2046 are running under Windows 9X), fallback to this: */
2047 else if (GetUserName (uname
, &ulength
))
2049 strcpy (dflt_passwd
.pw_name
, uname
);
2050 if (xstrcasecmp ("administrator", uname
) == 0)
2051 dflt_passwd
.pw_uid
= 0;
2053 dflt_passwd
.pw_uid
= 123;
2054 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2058 strcpy (dflt_passwd
.pw_name
, "unknown");
2059 dflt_passwd
.pw_uid
= 123;
2060 dflt_passwd
.pw_gid
= 123;
2062 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2064 /* Set dir and shell from environment variables. */
2065 if (w32_unicode_filenames
)
2067 wchar_t *home
= _wgetenv (L
"HOME");
2068 wchar_t *shell
= _wgetenv (L
"SHELL");
2070 /* Ensure HOME and SHELL are defined. */
2075 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2076 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2080 char *home
= getenv ("HOME");
2081 char *shell
= getenv ("SHELL");
2087 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2088 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2093 CloseHandle (token
);
2099 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2100 return ((rand () << 15) | rand ());
2109 /* Return the maximum length in bytes of a multibyte character
2110 sequence encoded in the current ANSI codepage. This is required to
2111 correctly walk the encoded file names one character at a time. */
2113 max_filename_mbslen (void)
2117 codepage_for_filenames (&cp_info
);
2118 return cp_info
.MaxCharSize
;
2121 /* Normalize filename by converting in-place all of its path
2122 separators to the separator specified by PATH_SEP. */
2125 normalize_filename (register char *fp
, char path_sep
)
2129 /* Always lower-case drive letters a-z, even if the filesystem
2130 preserves case in filenames.
2131 This is so filenames can be compared by string comparison
2132 functions that are case-sensitive. Even case-preserving filesystems
2133 do not distinguish case in drive letters. */
2136 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2144 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2150 /* Destructively turn backslashes into slashes. */
2152 dostounix_filename (register char *p
)
2154 normalize_filename (p
, '/');
2157 /* Destructively turn slashes into backslashes. */
2159 unixtodos_filename (register char *p
)
2161 normalize_filename (p
, '\\');
2164 /* Remove all CR's that are followed by a LF.
2165 (From msdos.c...probably should figure out a way to share it,
2166 although this code isn't going to ever change.) */
2168 crlf_to_lf (register int n
, register unsigned char *buf
)
2170 unsigned char *np
= buf
;
2171 unsigned char *startp
= buf
;
2172 unsigned char *endp
= buf
+ n
;
2176 while (buf
< endp
- 1)
2180 if (*(++buf
) != 0x0a)
2191 /* Parse the root part of file name, if present. Return length and
2192 optionally store pointer to char after root. */
2194 parse_root (const char * name
, const char ** pPath
)
2196 const char * start
= name
;
2201 /* find the root name of the volume if given */
2202 if (isalpha (name
[0]) && name
[1] == ':')
2204 /* skip past drive specifier */
2206 if (IS_DIRECTORY_SEP (name
[0]))
2209 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2216 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2221 if (IS_DIRECTORY_SEP (name
[0]))
2228 return name
- start
;
2231 /* Get long base name for name; name is assumed to be absolute. */
2233 get_long_basename (char * name
, char * buf
, int size
)
2235 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2236 char fname_utf8
[MAX_UTF8_PATH
];
2240 /* Must be valid filename, no wild cards or other invalid characters. */
2241 if (strpbrk (name
, "*?|<>\""))
2244 if (w32_unicode_filenames
)
2246 wchar_t fname_utf16
[MAX_PATH
];
2247 WIN32_FIND_DATAW find_data_wide
;
2249 filename_to_utf16 (name
, fname_utf16
);
2250 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2251 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2252 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2256 char fname_ansi
[MAX_PATH
];
2257 WIN32_FIND_DATAA find_data_ansi
;
2259 filename_to_ansi (name
, fname_ansi
);
2260 /* If the ANSI name includes ? characters, it is not encodable
2261 in the ANSI codepage. In that case, we deliver the question
2262 marks to the caller; calling FindFirstFileA in this case
2263 could return some unrelated file name in the same
2265 if (_mbspbrk (fname_ansi
, "?"))
2267 /* Find the basename of fname_ansi. */
2268 char *p
= strrchr (fname_ansi
, '\\');
2274 cstatus
= filename_from_ansi (p
, fname_utf8
);
2278 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2279 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2280 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2284 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2285 memcpy (buf
, fname_utf8
, len
+ 1);
2289 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2290 FindClose (dir_handle
);
2295 /* Get long name for file, if possible (assumed to be absolute). */
2297 w32_get_long_filename (const char * name
, char * buf
, int size
)
2302 char full
[ MAX_UTF8_PATH
];
2305 len
= strlen (name
);
2306 if (len
>= MAX_UTF8_PATH
)
2309 /* Use local copy for destructive modification. */
2310 memcpy (full
, name
, len
+1);
2311 unixtodos_filename (full
);
2313 /* Copy root part verbatim. */
2314 len
= parse_root (full
, (const char **)&p
);
2315 memcpy (o
, full
, len
);
2320 while (p
!= NULL
&& *p
)
2323 p
= strchr (q
, '\\');
2325 len
= get_long_basename (full
, o
, size
);
2348 w32_get_short_filename (const char * name
, char * buf
, int size
)
2350 if (w32_unicode_filenames
)
2352 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2353 unsigned int retval
;
2355 filename_to_utf16 (name
, name_utf16
);
2356 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2357 if (retval
&& retval
< size
)
2358 filename_from_utf16 (short_name
, buf
);
2363 char name_ansi
[MAX_PATH
];
2365 filename_to_ansi (name
, name_ansi
);
2366 return GetShortPathNameA (name_ansi
, buf
, size
);
2370 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2371 MS-Windows ANSI codepage. If FILENAME includes characters not
2372 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2373 if it exists. This is needed because the w32 build wants to
2374 support file names outside of the system locale, but image
2375 libraries typically don't support wide (a.k.a. "Unicode") APIs
2376 required for that. */
2379 ansi_encode_filename (Lisp_Object filename
)
2381 Lisp_Object encoded_filename
;
2382 char fname
[MAX_PATH
];
2384 filename_to_ansi (SSDATA (filename
), fname
);
2385 if (_mbspbrk (fname
, "?"))
2387 char shortname
[MAX_PATH
];
2389 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2391 dostounix_filename (shortname
);
2392 encoded_filename
= build_string (shortname
);
2395 encoded_filename
= build_unibyte_string (fname
);
2398 encoded_filename
= build_unibyte_string (fname
);
2399 return encoded_filename
;
2403 is_unc_volume (const char *filename
)
2405 const char *ptr
= filename
;
2407 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2410 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2416 /* Emulate the Posix unsetenv. */
2418 unsetenv (const char *name
)
2423 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2428 name_len
= strlen (name
);
2429 /* MS docs says an environment variable cannot be longer than 32K. */
2430 if (name_len
> 32767)
2435 /* It is safe to use 'alloca' with 32K size, since the stack is at
2436 least 2MB, and we set it to 8MB in the link command line. */
2437 var
= alloca (name_len
+ 2);
2438 strncpy (var
, name
, name_len
);
2439 var
[name_len
++] = '=';
2440 var
[name_len
] = '\0';
2441 return _putenv (var
);
2444 /* MS _putenv doesn't support removing a variable when the argument
2445 does not include the '=' character, so we fix that here. */
2447 sys_putenv (char *str
)
2449 const char *const name_end
= strchr (str
, '=');
2451 if (name_end
== NULL
)
2453 /* Remove the variable from the environment. */
2454 return unsetenv (str
);
2457 return _putenv (str
);
2460 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2463 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2466 HKEY hrootkey
= NULL
;
2469 /* Check both the current user and the local machine to see if
2470 we have any resources. */
2472 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2476 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2477 && (lpvalue
= xmalloc (cbData
)) != NULL
2478 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2480 RegCloseKey (hrootkey
);
2486 RegCloseKey (hrootkey
);
2489 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2493 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2494 && (lpvalue
= xmalloc (cbData
)) != NULL
2495 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2497 RegCloseKey (hrootkey
);
2503 RegCloseKey (hrootkey
);
2509 /* The argv[] array holds ANSI-encoded strings, and so this function
2510 works with ANS_encoded strings. */
2512 init_environment (char ** argv
)
2514 static const char * const tempdirs
[] = {
2515 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2520 const int imax
= ARRAYELTS (tempdirs
);
2522 /* Implementation note: This function explicitly works with ANSI
2523 file names, not with UTF-8 encoded file names. This is because
2524 this function pushes variables into the Emacs's environment, and
2525 the environment variables are always assumed to be in the
2526 locale-specific encoding. Do NOT call any functions that accept
2527 UTF-8 file names from this function! */
2529 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2530 temporary files and assume "/tmp" if $TMPDIR is unset, which
2531 will break on DOS/Windows. Refuse to work if we cannot find
2532 a directory, not even "c:/", usable for that purpose. */
2533 for (i
= 0; i
< imax
; i
++)
2535 const char *tmp
= tempdirs
[i
];
2538 tmp
= getenv (tmp
+ 1);
2539 /* Note that `access' can lie to us if the directory resides on a
2540 read-only filesystem, like CD-ROM or a write-protected floppy.
2541 The only way to be really sure is to actually create a file and
2542 see if it succeeds. But I think that's too much to ask. */
2544 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2545 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2547 char * var
= alloca (strlen (tmp
) + 8);
2548 sprintf (var
, "TMPDIR=%s", tmp
);
2549 _putenv (strdup (var
));
2556 Fcons (build_string ("no usable temporary directories found!!"),
2558 "While setting TMPDIR: ");
2560 /* Check for environment variables and use registry settings if they
2561 don't exist. Fallback on default values where applicable. */
2566 char locale_name
[32];
2567 char default_home
[MAX_PATH
];
2570 static const struct env_entry
2576 /* If the default value is NULL, we will use the value from the
2577 outside environment or the Registry, but will not push the
2578 variable into the Emacs environment if it is defined neither
2579 in the Registry nor in the outside environment. */
2581 {"PRELOAD_WINSOCK", NULL
},
2582 {"emacs_dir", "C:/emacs"},
2583 {"EMACSLOADPATH", NULL
},
2584 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2585 {"EMACSDATA", NULL
},
2586 {"EMACSPATH", NULL
},
2593 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2595 /* We need to copy dflt_envvars[] and work on the copy because we
2596 don't want the dumped Emacs to inherit the values of
2597 environment variables we saw during dumping (which could be on
2598 a different system). The defaults above must be left intact. */
2599 struct env_entry env_vars
[N_ENV_VARS
];
2601 for (i
= 0; i
< N_ENV_VARS
; i
++)
2602 env_vars
[i
] = dflt_envvars
[i
];
2604 /* For backwards compatibility, check if a .emacs file exists in C:/
2605 If not, then we can try to default to the appdata directory under the
2606 user's profile, which is more likely to be writable. */
2607 if (sys_access ("C:/.emacs", F_OK
) != 0)
2609 HRESULT profile_result
;
2610 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2611 of Windows 95 and NT4 that have not been updated to include
2613 ShGetFolderPath_fn get_folder_path
;
2614 get_folder_path
= (ShGetFolderPath_fn
)
2615 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2617 if (get_folder_path
!= NULL
)
2619 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2622 /* If we can't get the appdata dir, revert to old behavior. */
2623 if (profile_result
== S_OK
)
2625 env_vars
[0].def_value
= default_home
;
2631 /* Get default locale info and use it for LANG. */
2632 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2633 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2634 locale_name
, sizeof (locale_name
)))
2636 for (i
= 0; i
< N_ENV_VARS
; i
++)
2638 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2640 env_vars
[i
].def_value
= locale_name
;
2646 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2648 /* Treat emacs_dir specially: set it unconditionally based on our
2652 char modname
[MAX_PATH
];
2654 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2656 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2660 if ((p
= _mbsrchr (modname
, '\\'))
2661 /* From bin means installed Emacs, from src means uninstalled. */
2662 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2664 char buf
[SET_ENV_BUF_SIZE
];
2665 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2668 for (p
= modname
; *p
; p
= CharNext (p
))
2669 if (*p
== '\\') *p
= '/';
2671 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2672 _putenv (strdup (buf
));
2673 /* If we are running from the Posix-like build tree, define
2674 SHELL to point to our own cmdproxy. The loop below will
2675 then disregard PATH_EXEC and the default value. */
2676 if (within_build_tree
)
2678 _snprintf (buf
, sizeof (buf
) - 1,
2679 "SHELL=%s/nt/cmdproxy.exe", modname
);
2680 _putenv (strdup (buf
));
2685 for (i
= 0; i
< N_ENV_VARS
; i
++)
2687 if (!getenv (env_vars
[i
].name
))
2690 char bufc
[SET_ENV_BUF_SIZE
];
2692 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2693 /* Also ignore empty environment variables. */
2698 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2700 /* Look for cmdproxy.exe in every directory in
2701 PATH_EXEC. FIXME: This does not find cmdproxy
2702 in nt/ when we run uninstalled. */
2703 char fname
[MAX_PATH
];
2704 const char *pstart
= PATH_EXEC
, *pend
;
2707 pend
= _mbschr (pstart
, ';');
2709 pend
= pstart
+ strlen (pstart
);
2710 /* Be defensive against series of ;;; characters. */
2713 strncpy (fname
, pstart
, pend
- pstart
);
2714 fname
[pend
- pstart
] = '/';
2715 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2716 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2718 if (sys_access (bufc
, F_OK
) == 0)
2731 /* If not found in any directory, use the
2732 default as the last resort. */
2733 lpval
= env_vars
[i
].def_value
;
2734 dwType
= REG_EXPAND_SZ
;
2740 lpval
= env_vars
[i
].def_value
;
2741 dwType
= REG_EXPAND_SZ
;
2743 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2744 Vdelayed_warnings_list
2745 = Fcons (listn (CONSTYPE_HEAP
, 2,
2746 intern ("initialization"),
2747 build_string ("Setting HOME to C:\\ by default is deprecated")),
2748 Vdelayed_warnings_list
);
2753 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2755 if (dwType
== REG_EXPAND_SZ
)
2756 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2757 else if (dwType
== REG_SZ
)
2758 strcpy (buf1
, lpval
);
2759 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2761 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2763 _putenv (strdup (buf2
));
2773 /* Rebuild system configuration to reflect invoking system. */
2774 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2776 /* Another special case: on NT, the PATH variable is actually named
2777 "Path" although cmd.exe (perhaps NT itself) arranges for
2778 environment variable lookup and setting to be case insensitive.
2779 However, Emacs assumes a fully case sensitive environment, so we
2780 need to change "Path" to "PATH" to match the expectations of
2781 various elisp packages. We do this by the sneaky method of
2782 modifying the string in the C runtime environ entry.
2784 The same applies to COMSPEC. */
2788 for (envp
= environ
; *envp
; envp
++)
2789 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2790 memcpy (*envp
, "PATH=", 5);
2791 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2792 memcpy (*envp
, "COMSPEC=", 8);
2795 /* Remember the initial working directory for getcwd. */
2796 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2797 Does it matter anywhere in Emacs? */
2798 if (w32_unicode_filenames
)
2800 wchar_t wstartup_dir
[MAX_PATH
];
2802 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2804 filename_from_utf16 (wstartup_dir
, startup_dir
);
2808 char astartup_dir
[MAX_PATH
];
2810 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2812 filename_from_ansi (astartup_dir
, startup_dir
);
2816 static char modname
[MAX_PATH
];
2818 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2823 /* Determine if there is a middle mouse button, to allow parse_button
2824 to decide whether right mouse events should be mouse-2 or
2826 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2831 /* Called from expand-file-name when default-directory is not a string. */
2834 emacs_root_dir (void)
2836 static char root_dir
[MAX_UTF8_PATH
];
2839 p
= getenv ("emacs_dir");
2842 filename_from_ansi (p
, root_dir
);
2843 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2844 dostounix_filename (root_dir
);
2848 #include <sys/timeb.h>
2850 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2852 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2857 tv
->tv_sec
= tb
.time
;
2858 tv
->tv_usec
= tb
.millitm
* 1000L;
2859 /* Implementation note: _ftime sometimes doesn't update the dstflag
2860 according to the new timezone when the system timezone is
2861 changed. We could fix that by using GetSystemTime and
2862 GetTimeZoneInformation, but that doesn't seem necessary, since
2863 Emacs always calls gettimeofday with the 2nd argument NULL (see
2864 current_emacs_time). */
2867 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2868 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2873 /* Emulate fdutimens. */
2875 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2876 TIMESPEC[0] and TIMESPEC[1], respectively.
2877 FD must be either negative -- in which case it is ignored --
2878 or a file descriptor that is open on FILE.
2879 If FD is nonnegative, then FILE can be NULL, which means
2880 use just futimes instead of utimes.
2881 If TIMESPEC is null, FAIL.
2882 Return 0 on success, -1 (setting errno) on failure. */
2885 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2892 if (fd
< 0 && !file
)
2897 /* _futime's prototype defines 2nd arg as having the type 'struct
2898 _utimbuf', while utime needs to accept 'struct utimbuf' for
2899 compatibility with Posix. So we need to use 2 different (but
2900 equivalent) types to avoid compiler warnings, sigh. */
2903 struct _utimbuf _ut
;
2905 _ut
.actime
= timespec
[0].tv_sec
;
2906 _ut
.modtime
= timespec
[1].tv_sec
;
2907 return _futime (fd
, &_ut
);
2913 ut
.actime
= timespec
[0].tv_sec
;
2914 ut
.modtime
= timespec
[1].tv_sec
;
2915 /* Call 'utime', which is implemented below, not the MS library
2916 function, which fails on directories. */
2917 return utime (file
, &ut
);
2922 /* ------------------------------------------------------------------------- */
2923 /* IO support and wrapper functions for the Windows API. */
2924 /* ------------------------------------------------------------------------- */
2926 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2927 on network directories, so we handle that case here.
2928 (Ulrich Leodolter, 1/11/95). */
2930 sys_ctime (const time_t *t
)
2932 char *str
= (char *) ctime (t
);
2933 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2936 /* Emulate sleep...we could have done this with a define, but that
2937 would necessitate including windows.h in the files that used it.
2938 This is much easier. */
2940 sys_sleep (int seconds
)
2942 Sleep (seconds
* 1000);
2945 /* Internal MSVC functions for low-level descriptor munging */
2946 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2947 extern int __cdecl
_free_osfhnd (int fd
);
2949 /* parallel array of private info on file handles */
2950 filedesc fd_info
[ MAXDESC
];
2952 typedef struct volume_info_data
{
2953 struct volume_info_data
* next
;
2955 /* time when info was obtained */
2958 /* actual volume info */
2967 /* Global referenced by various functions. */
2968 static volume_info_data volume_info
;
2970 /* Vector to indicate which drives are local and fixed (for which cached
2971 data never expires). */
2972 static BOOL fixed_drives
[26];
2974 /* Consider cached volume information to be stale if older than 10s,
2975 at least for non-local drives. Info for fixed drives is never stale. */
2976 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2977 #define VOLINFO_STILL_VALID( root_dir, info ) \
2978 ( ( isalpha (root_dir[0]) && \
2979 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2980 || GetTickCount () - info->timestamp < 10000 )
2982 /* Cache support functions. */
2984 /* Simple linked list with linear search is sufficient. */
2985 static volume_info_data
*volume_cache
= NULL
;
2987 static volume_info_data
*
2988 lookup_volume_info (char * root_dir
)
2990 volume_info_data
* info
;
2992 for (info
= volume_cache
; info
; info
= info
->next
)
2993 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2999 add_volume_info (char * root_dir
, volume_info_data
* info
)
3001 info
->root_dir
= xstrdup (root_dir
);
3002 unixtodos_filename (info
->root_dir
);
3003 info
->next
= volume_cache
;
3004 volume_cache
= info
;
3008 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3009 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3010 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3011 static volume_info_data
*
3012 GetCachedVolumeInformation (char * root_dir
)
3014 volume_info_data
* info
;
3015 char default_root
[ MAX_UTF8_PATH
];
3016 char name
[MAX_PATH
+1];
3017 char type
[MAX_PATH
+1];
3019 /* NULL for root_dir means use root from current directory. */
3020 if (root_dir
== NULL
)
3022 if (w32_unicode_filenames
)
3024 wchar_t curdirw
[MAX_PATH
];
3026 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3028 filename_from_utf16 (curdirw
, default_root
);
3032 char curdira
[MAX_PATH
];
3034 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3036 filename_from_ansi (curdira
, default_root
);
3038 parse_root (default_root
, (const char **)&root_dir
);
3040 root_dir
= default_root
;
3043 /* Local fixed drives can be cached permanently. Removable drives
3044 cannot be cached permanently, since the volume name and serial
3045 number (if nothing else) can change. Remote drives should be
3046 treated as if they are removable, since there is no sure way to
3047 tell whether they are or not. Also, the UNC association of drive
3048 letters mapped to remote volumes can be changed at any time (even
3049 by other processes) without notice.
3051 As a compromise, so we can benefit from caching info for remote
3052 volumes, we use a simple expiry mechanism to invalidate cache
3053 entries that are more than ten seconds old. */
3056 /* No point doing this, because WNetGetConnection is even slower than
3057 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3058 GetDriveType is about the only call of this type which does not
3059 involve network access, and so is extremely quick). */
3061 /* Map drive letter to UNC if remote. */
3062 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3064 char remote_name
[ 256 ];
3065 char drive
[3] = { root_dir
[0], ':' };
3067 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3069 /* do something */ ;
3073 info
= lookup_volume_info (root_dir
);
3075 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3081 /* Info is not cached, or is stale. */
3082 if (w32_unicode_filenames
)
3084 wchar_t root_w
[MAX_PATH
];
3085 wchar_t name_w
[MAX_PATH
+1];
3086 wchar_t type_w
[MAX_PATH
+1];
3088 filename_to_utf16 (root_dir
, root_w
);
3089 if (!GetVolumeInformationW (root_w
,
3090 name_w
, sizeof (name_w
),
3094 type_w
, sizeof (type_w
)))
3096 /* Hmm... not really 100% correct, as these 2 are not file
3098 filename_from_utf16 (name_w
, name
);
3099 filename_from_utf16 (type_w
, type
);
3103 char root_a
[MAX_PATH
];
3104 char name_a
[MAX_PATH
+1];
3105 char type_a
[MAX_PATH
+1];
3107 filename_to_ansi (root_dir
, root_a
);
3108 if (!GetVolumeInformationA (root_a
,
3109 name_a
, sizeof (name_a
),
3113 type_a
, sizeof (type_a
)))
3115 filename_from_ansi (name_a
, name
);
3116 filename_from_ansi (type_a
, type
);
3119 /* Cache the volume information for future use, overwriting existing
3120 entry if present. */
3123 info
= xmalloc (sizeof (volume_info_data
));
3124 add_volume_info (root_dir
, info
);
3132 info
->name
= xstrdup (name
);
3133 unixtodos_filename (info
->name
);
3134 info
->serialnum
= serialnum
;
3135 info
->maxcomp
= maxcomp
;
3136 info
->flags
= flags
;
3137 info
->type
= xstrdup (type
);
3138 info
->timestamp
= GetTickCount ();
3144 /* Get information on the volume where NAME is held; set path pointer to
3145 start of pathname in NAME (past UNC header\volume header if present),
3146 if pPath is non-NULL.
3148 Note: if NAME includes symlinks, the information is for the volume
3149 of the symlink, not of its target. That's because, even though
3150 GetVolumeInformation returns information about the symlink target
3151 of its argument, we only pass the root directory to
3152 GetVolumeInformation, not the full NAME. */
3154 get_volume_info (const char * name
, const char ** pPath
)
3156 char temp
[MAX_UTF8_PATH
];
3157 char *rootname
= NULL
; /* default to current volume */
3158 volume_info_data
* info
;
3159 int root_len
= parse_root (name
, pPath
);
3164 /* Copy the root name of the volume, if given. */
3167 strncpy (temp
, name
, root_len
);
3168 temp
[root_len
] = '\0';
3169 unixtodos_filename (temp
);
3173 info
= GetCachedVolumeInformation (rootname
);
3176 /* Set global referenced by other functions. */
3177 volume_info
= *info
;
3183 /* Determine if volume is FAT format (ie. only supports short 8.3
3184 names); also set path pointer to start of pathname in name, if
3185 pPath is non-NULL. */
3187 is_fat_volume (const char * name
, const char ** pPath
)
3189 if (get_volume_info (name
, pPath
))
3190 return (volume_info
.maxcomp
== 12);
3194 /* Convert all slashes in a filename to backslashes, and map filename
3195 to a valid 8.3 name if necessary. The result is a pointer to a
3196 static buffer, so CAVEAT EMPTOR! */
3198 map_w32_filename (const char * name
, const char ** pPath
)
3200 static char shortname
[MAX_UTF8_PATH
];
3201 char * str
= shortname
;
3204 const char * save_name
= name
;
3206 if (strlen (name
) >= sizeof (shortname
))
3208 /* Return a filename which will cause callers to fail. */
3209 strcpy (shortname
, "?");
3213 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3215 register int left
= 8; /* maximum number of chars in part */
3216 register int extn
= 0; /* extension added? */
3217 register int dots
= 2; /* maximum number of dots allowed */
3220 *str
++ = *name
++; /* skip past UNC header */
3222 while ((c
= *name
++))
3229 *str
++ = (c
== ':' ? ':' : '\\');
3230 extn
= 0; /* reset extension flags */
3231 dots
= 2; /* max 2 dots */
3232 left
= 8; /* max length 8 for main part */
3237 /* Convert path components of the form .xxx to _xxx,
3238 but leave . and .. as they are. This allows .emacs
3239 to be read as _emacs, for example. */
3243 IS_DIRECTORY_SEP (*name
))
3258 extn
= 1; /* we've got an extension */
3259 left
= 3; /* 3 chars in extension */
3263 /* any embedded dots after the first are converted to _ */
3268 case '#': /* don't lose these, they're important */
3270 str
[-1] = c
; /* replace last character of part */
3273 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3275 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3277 dots
= 0; /* started a path component */
3286 strcpy (shortname
, name
);
3287 unixtodos_filename (shortname
);
3291 *pPath
= shortname
+ (path
- save_name
);
3297 is_exec (const char * name
)
3299 char * p
= strrchr (name
, '.');
3302 && (xstrcasecmp (p
, ".exe") == 0 ||
3303 xstrcasecmp (p
, ".com") == 0 ||
3304 xstrcasecmp (p
, ".bat") == 0 ||
3305 xstrcasecmp (p
, ".cmd") == 0));
3308 /* Emulate the Unix directory procedures opendir, closedir, and
3309 readdir. We rename them to sys_* names because some versions of
3310 MinGW startup code call opendir and readdir to glob wildcards, and
3311 the code that calls them doesn't grok UTF-8 encoded file names we
3312 produce in dirent->d_name[]. */
3314 struct dirent dir_static
; /* simulated directory contents */
3315 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3316 static int dir_is_fat
;
3317 static char dir_pathname
[MAX_UTF8_PATH
];
3318 static WIN32_FIND_DATAW dir_find_data_w
;
3319 static WIN32_FIND_DATAA dir_find_data_a
;
3320 #define DIR_FIND_DATA_W 1
3321 #define DIR_FIND_DATA_A 2
3322 static int last_dir_find_data
= -1;
3324 /* Support shares on a network resource as subdirectories of a read-only
3326 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3327 static HANDLE
open_unc_volume (const char *);
3328 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3329 static void close_unc_volume (HANDLE
);
3332 sys_opendir (const char *filename
)
3336 /* Opening is done by FindFirstFile. However, a read is inherent to
3337 this operation, so we defer the open until read time. */
3339 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3341 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3344 /* Note: We don't support traversal of UNC volumes via symlinks.
3345 Doing so would mean punishing 99.99% of use cases by resolving
3346 all the possible symlinks in FILENAME, recursively. */
3347 if (is_unc_volume (filename
))
3349 wnet_enum_handle
= open_unc_volume (filename
);
3350 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3354 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3361 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3362 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3363 /* Note: We don't support symlinks to file names on FAT volumes.
3364 Doing so would mean punishing 99.99% of use cases by resolving
3365 all the possible symlinks in FILENAME, recursively. */
3366 dir_is_fat
= is_fat_volume (filename
, NULL
);
3372 sys_closedir (DIR *dirp
)
3374 /* If we have a find-handle open, close it. */
3375 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3377 FindClose (dir_find_handle
);
3378 dir_find_handle
= INVALID_HANDLE_VALUE
;
3380 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3382 close_unc_volume (wnet_enum_handle
);
3383 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3385 xfree ((char *) dirp
);
3389 sys_readdir (DIR *dirp
)
3391 int downcase
= !NILP (Vw32_downcase_file_names
);
3393 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3395 if (!read_unc_volume (wnet_enum_handle
,
3396 dir_find_data_w
.cFileName
,
3397 dir_find_data_a
.cFileName
,
3401 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3402 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3404 char filename
[MAX_UTF8_PATH
];
3406 bool last_slash
= true;
3408 /* Note: We don't need to worry about dir_pathname being longer
3409 than MAX_UTF8_PATH, as sys_opendir already took care of that
3410 when it called map_w32_filename: that function will put a "?"
3411 in its return value in that case, thus failing all the calls
3413 strcpy (filename
, dir_pathname
);
3414 ln
= strlen (filename
);
3415 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3418 /* Note: No need to resolve symlinks in FILENAME, because
3419 FindFirst opens the directory that is the target of a
3421 if (w32_unicode_filenames
)
3423 wchar_t fnw
[MAX_PATH
+ 2];
3425 filename_to_utf16 (filename
, fnw
);
3427 wcscat (fnw
, L
"\\");
3429 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3433 char fna
[MAX_PATH
+ 2];
3435 filename_to_ansi (filename
, fna
);
3439 /* If FILENAME is not representable by the current ANSI
3440 codepage, we don't want FindFirstFileA to interpret the
3441 '?' characters as a wildcard. */
3442 if (_mbspbrk (fna
, "?"))
3443 dir_find_handle
= INVALID_HANDLE_VALUE
;
3445 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3448 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3450 /* Any changes in the value of errno here should be in sync
3451 with what directory_files_internal does when it calls
3453 switch (GetLastError ())
3455 /* Windows uses this value when FindFirstFile finds no
3456 files that match the wildcard. This is not supposed
3457 to happen, since our wildcard is "*", but just in
3458 case, if there's some weird empty directory with not
3459 even "." and ".." entries... */
3460 case ERROR_FILE_NOT_FOUND
:
3465 case ERROR_ACCESS_DENIED
:
3466 case ERROR_NETWORK_ACCESS_DENIED
:
3469 case ERROR_PATH_NOT_FOUND
:
3470 case ERROR_INVALID_DRIVE
:
3471 case ERROR_NOT_READY
:
3472 case ERROR_BAD_NETPATH
:
3473 case ERROR_BAD_NET_NAME
:
3480 else if (w32_unicode_filenames
)
3482 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3490 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3497 /* Emacs never uses this value, so don't bother making it match
3498 value returned by stat(). */
3499 dir_static
.d_ino
= 1;
3501 if (w32_unicode_filenames
)
3503 if (downcase
|| dir_is_fat
)
3505 wchar_t tem
[MAX_PATH
];
3507 wcscpy (tem
, dir_find_data_w
.cFileName
);
3509 filename_from_utf16 (tem
, dir_static
.d_name
);
3512 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3513 last_dir_find_data
= DIR_FIND_DATA_W
;
3519 /* If the file name in cFileName[] includes `?' characters, it
3520 means the original file name used characters that cannot be
3521 represented by the current ANSI codepage. To avoid total
3522 lossage, retrieve the short 8+3 alias of the long file
3524 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3526 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3527 /* 8+3 aliases are returned in all caps, which could break
3528 various alists that look at filenames' extensions. */
3531 else if (downcase
|| dir_is_fat
)
3532 strcpy (tem
, dir_find_data_a
.cFileName
);
3534 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3535 if (downcase
|| dir_is_fat
)
3538 filename_from_ansi (tem
, dir_static
.d_name
);
3540 last_dir_find_data
= DIR_FIND_DATA_A
;
3543 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3544 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3545 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3551 open_unc_volume (const char *path
)
3553 const char *fn
= map_w32_filename (path
, NULL
);
3557 if (w32_unicode_filenames
)
3560 wchar_t fnw
[MAX_PATH
];
3562 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3563 nrw
.dwType
= RESOURCETYPE_DISK
;
3564 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3565 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3566 nrw
.lpLocalName
= NULL
;
3567 filename_to_utf16 (fn
, fnw
);
3568 nrw
.lpRemoteName
= fnw
;
3569 nrw
.lpComment
= NULL
;
3570 nrw
.lpProvider
= NULL
;
3572 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3573 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3580 nra
.dwScope
= RESOURCE_GLOBALNET
;
3581 nra
.dwType
= RESOURCETYPE_DISK
;
3582 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3583 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3584 nra
.lpLocalName
= NULL
;
3585 filename_to_ansi (fn
, fna
);
3586 nra
.lpRemoteName
= fna
;
3587 nra
.lpComment
= NULL
;
3588 nra
.lpProvider
= NULL
;
3590 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3591 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3593 if (result
== NO_ERROR
)
3597 /* Make sure directory_files_internal reports a sensible error. */
3599 return INVALID_HANDLE_VALUE
;
3604 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3609 DWORD bufsize
= 512;
3613 if (w32_unicode_filenames
)
3618 buffer
= alloca (bufsize
);
3619 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3620 if (result
!= NO_ERROR
)
3622 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3623 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3625 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3627 wcsncpy (fname_w
, ptrw
, size
);
3632 int dbcs_p
= max_filename_mbslen () > 1;
3635 buffer
= alloca (bufsize
);
3636 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3637 if (result
!= NO_ERROR
)
3639 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3642 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3645 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3646 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3649 strncpy (fname_a
, ptra
, size
);
3657 close_unc_volume (HANDLE henum
)
3659 if (henum
!= INVALID_HANDLE_VALUE
)
3660 WNetCloseEnum (henum
);
3664 unc_volume_file_attributes (const char *path
)
3669 henum
= open_unc_volume (path
);
3670 if (henum
== INVALID_HANDLE_VALUE
)
3673 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3675 close_unc_volume (henum
);
3680 /* Ensure a network connection is authenticated. */
3682 logon_network_drive (const char *path
)
3684 char share
[MAX_UTF8_PATH
];
3691 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3692 drvtype
= DRIVE_REMOTE
;
3693 else if (path
[0] == '\0' || path
[1] != ':')
3694 drvtype
= GetDriveType (NULL
);
3701 drvtype
= GetDriveType (drive
);
3704 /* Only logon to networked drives. */
3705 if (drvtype
!= DRIVE_REMOTE
)
3709 strncpy (share
, path
, MAX_UTF8_PATH
);
3710 /* Truncate to just server and share name. */
3711 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3713 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3720 if (w32_unicode_filenames
)
3722 NETRESOURCEW resourcew
;
3723 wchar_t share_w
[MAX_PATH
];
3725 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3726 resourcew
.dwType
= RESOURCETYPE_DISK
;
3727 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3728 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3729 resourcew
.lpLocalName
= NULL
;
3730 filename_to_utf16 (share
, share_w
);
3731 resourcew
.lpRemoteName
= share_w
;
3732 resourcew
.lpProvider
= NULL
;
3734 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3738 NETRESOURCEA resourcea
;
3739 char share_a
[MAX_PATH
];
3741 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3742 resourcea
.dwType
= RESOURCETYPE_DISK
;
3743 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3744 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3745 resourcea
.lpLocalName
= NULL
;
3746 filename_to_ansi (share
, share_a
);
3747 resourcea
.lpRemoteName
= share_a
;
3748 resourcea
.lpProvider
= NULL
;
3750 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3756 case ERROR_ALREADY_ASSIGNED
:
3758 case ERROR_ACCESS_DENIED
:
3759 case ERROR_LOGON_FAILURE
:
3765 case ERROR_BAD_NET_NAME
:
3766 case ERROR_NO_NET_OR_BAD_PATH
:
3767 case ERROR_NO_NETWORK
:
3768 case ERROR_CANCELLED
:
3775 /* Emulate faccessat(2). */
3777 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3781 if (dirfd
!= AT_FDCWD
3782 && !(IS_DIRECTORY_SEP (path
[0])
3783 || IS_DEVICE_SEP (path
[1])))
3789 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3790 newer versions blow up when passed D_OK. */
3791 path
= map_w32_filename (path
, NULL
);
3792 /* If the last element of PATH is a symlink, we need to resolve it
3793 to get the attributes of its target file. Note: any symlinks in
3794 PATH elements other than the last one are transparently resolved
3795 by GetFileAttributes below. */
3796 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3797 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3798 path
= chase_symlinks (path
);
3800 if (w32_unicode_filenames
)
3802 wchar_t path_w
[MAX_PATH
];
3804 filename_to_utf16 (path
, path_w
);
3805 attributes
= GetFileAttributesW (path_w
);
3809 char path_a
[MAX_PATH
];
3811 filename_to_ansi (path
, path_a
);
3812 attributes
= GetFileAttributesA (path_a
);
3815 if (attributes
== -1)
3817 DWORD w32err
= GetLastError ();
3821 case ERROR_INVALID_NAME
:
3822 case ERROR_BAD_PATHNAME
:
3823 if (is_unc_volume (path
))
3825 attributes
= unc_volume_file_attributes (path
);
3826 if (attributes
== -1)
3834 case ERROR_FILE_NOT_FOUND
:
3835 case ERROR_BAD_NETPATH
:
3846 if ((mode
& X_OK
) != 0
3847 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3852 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3857 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3865 /* A special test for DIRNAME being a directory accessible by the
3866 current user. This is needed because the security permissions in
3867 directory's ACLs are not visible in the Posix-style mode bits
3868 returned by 'stat' and in attributes returned by GetFileAttributes.
3869 So a directory would seem like it's readable by the current user,
3870 but will in fact error out with EACCES when they actually try. */
3872 w32_accessible_directory_p (const char *dirname
, ptrdiff_t dirlen
)
3874 char pattern
[MAX_UTF8_PATH
];
3875 bool last_slash
= dirlen
> 0 && IS_DIRECTORY_SEP (dirname
[dirlen
- 1]);
3878 /* Network volumes need a different reading method. */
3879 if (is_unc_volume (dirname
))
3881 void *read_result
= NULL
;
3882 wchar_t fnw
[MAX_PATH
];
3885 dh
= open_unc_volume (dirname
);
3886 if (dh
!= INVALID_HANDLE_VALUE
)
3888 read_result
= read_unc_volume (dh
, fnw
, fna
, MAX_PATH
);
3889 close_unc_volume (dh
);
3891 /* Treat empty volumes as accessible. */
3892 return read_result
!= NULL
|| GetLastError () == ERROR_NO_MORE_ITEMS
;
3895 /* Note: map_w32_filename makes sure DIRNAME is not longer than
3897 strcpy (pattern
, map_w32_filename (dirname
, NULL
));
3899 /* Note: No need to resolve symlinks in FILENAME, because FindFirst
3900 opens the directory that is the target of a symlink. */
3901 if (w32_unicode_filenames
)
3903 wchar_t pat_w
[MAX_PATH
+ 2];
3904 WIN32_FIND_DATAW dfd_w
;
3906 filename_to_utf16 (pattern
, pat_w
);
3908 wcscat (pat_w
, L
"\\");
3909 wcscat (pat_w
, L
"*");
3910 dh
= FindFirstFileW (pat_w
, &dfd_w
);
3914 char pat_a
[MAX_PATH
+ 2];
3915 WIN32_FIND_DATAA dfd_a
;
3917 filename_to_ansi (pattern
, pat_a
);
3919 strcpy (pat_a
, "\\");
3920 strcat (pat_a
, "*");
3921 /* In case DIRNAME cannot be expressed in characters from the
3922 current ANSI codepage. */
3923 if (_mbspbrk (pat_a
, "?"))
3924 dh
= INVALID_HANDLE_VALUE
;
3926 dh
= FindFirstFileA (pat_a
, &dfd_a
);
3929 if (dh
== INVALID_HANDLE_VALUE
)
3935 /* A version of 'access' to be used locally with file names in
3936 locale-specific encoding. Does not resolve symlinks and does not
3937 support file names on FAT12 and FAT16 volumes, but that's OK, since
3938 we only invoke this function for files inside the Emacs source or
3939 installation tree, on directories (so any symlinks should have the
3940 directory bit set), and on short file names such as "C:/.emacs". */
3942 sys_access (const char *fname
, int mode
)
3944 char fname_copy
[MAX_PATH
], *p
;
3947 strcpy (fname_copy
, fname
);
3948 /* Do the equivalent of unixtodos_filename. */
3949 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3953 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3955 DWORD w32err
= GetLastError ();
3959 case ERROR_INVALID_NAME
:
3960 case ERROR_BAD_PATHNAME
:
3961 case ERROR_FILE_NOT_FOUND
:
3962 case ERROR_BAD_NETPATH
:
3971 if ((mode
& X_OK
) != 0
3972 && !(is_exec (fname_copy
)
3973 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3978 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3983 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3991 /* Shadow some MSVC runtime functions to map requests for long filenames
3992 to reasonable short names if necessary. This was originally added to
3993 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3997 sys_chdir (const char * path
)
3999 path
= map_w32_filename (path
, NULL
);
4000 if (w32_unicode_filenames
)
4002 wchar_t newdir_w
[MAX_PATH
];
4004 if (filename_to_utf16 (path
, newdir_w
) == 0)
4005 return _wchdir (newdir_w
);
4010 char newdir_a
[MAX_PATH
];
4012 if (filename_to_ansi (path
, newdir_a
) == 0)
4013 return _chdir (newdir_a
);
4019 sys_chmod (const char * path
, int mode
)
4021 path
= chase_symlinks (map_w32_filename (path
, NULL
));
4022 if (w32_unicode_filenames
)
4024 wchar_t path_w
[MAX_PATH
];
4026 filename_to_utf16 (path
, path_w
);
4027 return _wchmod (path_w
, mode
);
4031 char path_a
[MAX_PATH
];
4033 filename_to_ansi (path
, path_a
);
4034 return _chmod (path_a
, mode
);
4039 sys_creat (const char * path
, int mode
)
4041 path
= map_w32_filename (path
, NULL
);
4042 if (w32_unicode_filenames
)
4044 wchar_t path_w
[MAX_PATH
];
4046 filename_to_utf16 (path
, path_w
);
4047 return _wcreat (path_w
, mode
);
4051 char path_a
[MAX_PATH
];
4053 filename_to_ansi (path
, path_a
);
4054 return _creat (path_a
, mode
);
4059 sys_fopen (const char * path
, const char * mode
)
4063 const char * mode_save
= mode
;
4065 /* Force all file handles to be non-inheritable. This is necessary to
4066 ensure child processes don't unwittingly inherit handles that might
4067 prevent future file access. */
4071 else if (mode
[0] == 'w' || mode
[0] == 'a')
4072 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
4076 /* Only do simplistic option parsing. */
4080 oflag
&= ~(O_RDONLY
| O_WRONLY
);
4083 else if (mode
[0] == 'b')
4088 else if (mode
[0] == 't')
4095 path
= map_w32_filename (path
, NULL
);
4096 if (w32_unicode_filenames
)
4098 wchar_t path_w
[MAX_PATH
];
4100 filename_to_utf16 (path
, path_w
);
4101 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
4105 char path_a
[MAX_PATH
];
4107 filename_to_ansi (path
, path_a
);
4108 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4113 return _fdopen (fd
, mode_save
);
4116 /* This only works on NTFS volumes, but is useful to have. */
4118 sys_link (const char * old
, const char * new)
4122 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4123 wchar_t oldname_w
[MAX_PATH
];
4124 char oldname_a
[MAX_PATH
];
4126 if (old
== NULL
|| new == NULL
)
4132 strcpy (oldname
, map_w32_filename (old
, NULL
));
4133 strcpy (newname
, map_w32_filename (new, NULL
));
4135 if (w32_unicode_filenames
)
4137 filename_to_utf16 (oldname
, oldname_w
);
4138 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4139 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4143 filename_to_ansi (oldname
, oldname_a
);
4144 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4145 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4147 if (fileh
!= INVALID_HANDLE_VALUE
)
4151 /* Confusingly, the "alternate" stream name field does not apply
4152 when restoring a hard link, and instead contains the actual
4153 stream data for the link (ie. the name of the link to create).
4154 The WIN32_STREAM_ID structure before the cStreamName field is
4155 the stream header, which is then immediately followed by the
4159 WIN32_STREAM_ID wid
;
4160 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4163 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4164 indicates that flag is unsupported for CP_UTF8, and OTOH says
4165 it is the default anyway. */
4166 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4167 data
.wid
.cStreamName
, MAX_PATH
);
4170 LPVOID context
= NULL
;
4173 data
.wid
.dwStreamId
= BACKUP_LINK
;
4174 data
.wid
.dwStreamAttributes
= 0;
4175 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4176 data
.wid
.Size
.HighPart
= 0;
4177 data
.wid
.dwStreamNameSize
= 0;
4179 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4180 offsetof (WIN32_STREAM_ID
, cStreamName
)
4181 + data
.wid
.Size
.LowPart
,
4182 &wbytes
, FALSE
, FALSE
, &context
)
4183 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4190 DWORD err
= GetLastError ();
4195 case ERROR_ACCESS_DENIED
:
4196 /* This is what happens when OLDNAME is a directory,
4197 since Windows doesn't support hard links to
4198 directories. Posix says to set errno to EPERM in
4200 if (w32_unicode_filenames
)
4201 attributes
= GetFileAttributesW (oldname_w
);
4203 attributes
= GetFileAttributesA (oldname_a
);
4204 if (attributes
!= -1
4205 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4207 else if (attributes
== -1
4208 && is_unc_volume (oldname
)
4209 && unc_volume_file_attributes (oldname
) != -1)
4214 case ERROR_TOO_MANY_LINKS
:
4217 case ERROR_NOT_SAME_DEVICE
:
4227 CloseHandle (fileh
);
4236 sys_mkdir (const char * path
)
4238 path
= map_w32_filename (path
, NULL
);
4240 if (w32_unicode_filenames
)
4242 wchar_t path_w
[MAX_PATH
];
4244 filename_to_utf16 (path
, path_w
);
4245 return _wmkdir (path_w
);
4249 char path_a
[MAX_PATH
];
4251 filename_to_ansi (path
, path_a
);
4252 return _mkdir (path_a
);
4257 sys_open (const char * path
, int oflag
, int mode
)
4259 const char* mpath
= map_w32_filename (path
, NULL
);
4262 if (w32_unicode_filenames
)
4264 wchar_t mpath_w
[MAX_PATH
];
4266 filename_to_utf16 (mpath
, mpath_w
);
4267 /* If possible, try to open file without _O_CREAT, to be able to
4268 write to existing hidden and system files. Force all file
4269 handles to be non-inheritable. */
4270 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4271 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4273 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4277 char mpath_a
[MAX_PATH
];
4279 filename_to_ansi (mpath
, mpath_a
);
4280 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4281 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4283 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4289 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4292 Standard algorithm for generating a temporary file name seems to be
4293 use pid or tid with a letter on the front (in place of the 6 X's)
4294 and cycle through the letters to find a unique name. We extend
4295 that to allow any reasonable character as the first of the 6 X's,
4296 so that the number of simultaneously used temporary files will be
4300 mkostemp (char * template, int flags
)
4304 unsigned uid
= GetCurrentThreadId ();
4305 int save_errno
= errno
;
4306 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4309 if (template == NULL
)
4312 p
= template + strlen (template);
4314 /* replace up to the last 5 X's with uid in decimal */
4315 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4317 p
[0] = '0' + uid
% 10;
4321 if (i
< 0 && p
[0] == 'X')
4326 p
[0] = first_char
[i
];
4327 if ((fd
= sys_open (template,
4328 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4329 S_IRUSR
| S_IWUSR
)) >= 0
4337 while (++i
< sizeof (first_char
));
4340 /* Template is badly formed or else we can't generate a unique name. */
4345 fchmod (int fd
, mode_t mode
)
4351 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4354 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4357 bool have_temp_a
= false;
4359 /* MoveFile on Windows 95 doesn't correctly change the short file name
4360 alias in a number of circumstances (it is not easy to predict when
4361 just by looking at oldname and newname, unfortunately). In these
4362 cases, renaming through a temporary name avoids the problem.
4364 A second problem on Windows 95 is that renaming through a temp name when
4365 newname is uppercase fails (the final long name ends up in
4366 lowercase, although the short alias might be uppercase) UNLESS the
4367 long temp name is not 8.3.
4369 So, on Windows 95 we always rename through a temp name, and we make sure
4370 the temp name has a long extension to ensure correct renaming. */
4372 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4374 /* volume_info is set indirectly by map_w32_filename. */
4375 oldname_dev
= volume_info
.serialnum
;
4377 if (os_subtype
== OS_9X
)
4382 char oldname_a
[MAX_PATH
];
4384 oldname
= map_w32_filename (oldname
, NULL
);
4385 filename_to_ansi (oldname
, oldname_a
);
4386 filename_to_ansi (temp
, temp_a
);
4387 if ((o
= strrchr (oldname_a
, '\\')))
4390 o
= (char *) oldname_a
;
4392 if ((p
= strrchr (temp_a
, '\\')))
4399 /* Force temp name to require a manufactured 8.3 alias - this
4400 seems to make the second rename work properly. */
4401 sprintf (p
, "_.%s.%u", o
, i
);
4403 result
= rename (oldname_a
, temp_a
);
4405 /* This loop must surely terminate! */
4406 while (result
< 0 && errno
== EEXIST
);
4412 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4413 (at least if it is a file; don't do this for directories).
4415 Since we mustn't do this if we are just changing the case of the
4416 file name (we would end up deleting the file we are trying to
4417 rename!), we let rename detect if the destination file already
4418 exists - that way we avoid the possible pitfalls of trying to
4419 determine ourselves whether two names really refer to the same
4420 file, which is not always possible in the general case. (Consider
4421 all the permutations of shared or subst'd drives, etc.) */
4423 newname
= map_w32_filename (newname
, NULL
);
4425 /* volume_info is set indirectly by map_w32_filename. */
4426 newname_dev
= volume_info
.serialnum
;
4428 if (w32_unicode_filenames
)
4430 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4432 filename_to_utf16 (temp
, temp_w
);
4433 filename_to_utf16 (newname
, newname_w
);
4434 result
= _wrename (temp_w
, newname_w
);
4435 if (result
< 0 && force
)
4437 DWORD w32err
= GetLastError ();
4440 && newname_dev
!= oldname_dev
)
4442 /* The implementation of `rename' on Windows does not return
4443 errno = EXDEV when you are moving a directory to a
4444 different storage device (ex. logical disk). It returns
4445 EACCES instead. So here we handle such situations and
4449 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4450 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4453 else if (errno
== EEXIST
)
4455 if (_wchmod (newname_w
, 0666) != 0)
4457 if (_wunlink (newname_w
) != 0)
4459 result
= _wrename (temp_w
, newname_w
);
4461 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4462 && is_symlink (temp
))
4464 /* This is Windows prohibiting the user from creating a
4465 symlink in another place, since that requires
4473 char newname_a
[MAX_PATH
];
4476 filename_to_ansi (temp
, temp_a
);
4477 filename_to_ansi (newname
, newname_a
);
4478 result
= rename (temp_a
, newname_a
);
4479 if (result
< 0 && force
)
4481 DWORD w32err
= GetLastError ();
4484 && newname_dev
!= oldname_dev
)
4488 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4489 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4492 else if (errno
== EEXIST
)
4494 if (_chmod (newname_a
, 0666) != 0)
4496 if (_unlink (newname_a
) != 0)
4498 result
= rename (temp_a
, newname_a
);
4500 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4501 && is_symlink (temp
))
4510 sys_rename (char const *old
, char const *new)
4512 return sys_rename_replace (old
, new, TRUE
);
4516 sys_rmdir (const char * path
)
4518 path
= map_w32_filename (path
, NULL
);
4520 if (w32_unicode_filenames
)
4522 wchar_t path_w
[MAX_PATH
];
4524 filename_to_utf16 (path
, path_w
);
4525 return _wrmdir (path_w
);
4529 char path_a
[MAX_PATH
];
4531 filename_to_ansi (path
, path_a
);
4532 return _rmdir (path_a
);
4537 sys_unlink (const char * path
)
4541 path
= map_w32_filename (path
, NULL
);
4543 if (w32_unicode_filenames
)
4545 wchar_t path_w
[MAX_PATH
];
4547 filename_to_utf16 (path
, path_w
);
4548 /* On Unix, unlink works without write permission. */
4549 _wchmod (path_w
, 0666);
4550 rmstatus
= _wunlink (path_w
);
4552 /* Symlinks to directories can only be deleted by _rmdir;
4553 _unlink returns EACCES. */
4556 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4557 rmstatus
= _wrmdir (path_w
);
4563 char path_a
[MAX_PATH
];
4565 filename_to_ansi (path
, path_a
);
4566 _chmod (path_a
, 0666);
4567 rmstatus
= _unlink (path_a
);
4571 && (is_symlink (path
) & FILE_ATTRIBUTE_DIRECTORY
) != 0)
4572 rmstatus
= _rmdir (path_a
);
4580 static FILETIME utc_base_ft
;
4581 static ULONGLONG utc_base
; /* In 100ns units */
4582 static int init
= 0;
4584 #define FILETIME_TO_U64(result, ft) \
4586 ULARGE_INTEGER uiTemp; \
4587 uiTemp.LowPart = (ft).dwLowDateTime; \
4588 uiTemp.HighPart = (ft).dwHighDateTime; \
4589 result = uiTemp.QuadPart; \
4593 initialize_utc_base (void)
4595 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4604 st
.wMilliseconds
= 0;
4606 SystemTimeToFileTime (&st
, &utc_base_ft
);
4607 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4611 convert_time (FILETIME ft
)
4617 initialize_utc_base ();
4621 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4624 FILETIME_TO_U64 (tmp
, ft
);
4625 return (time_t) ((tmp
- utc_base
) / 10000000L);
4629 convert_from_time_t (time_t time
, FILETIME
* pft
)
4635 initialize_utc_base ();
4639 /* time in 100ns units since 1-Jan-1601 */
4640 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4641 pft
->dwHighDateTime
= tmp
.HighPart
;
4642 pft
->dwLowDateTime
= tmp
.LowPart
;
4645 static PSECURITY_DESCRIPTOR
4646 get_file_security_desc_by_handle (HANDLE h
)
4648 PSECURITY_DESCRIPTOR psd
= NULL
;
4650 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4651 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4653 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4654 NULL
, NULL
, NULL
, NULL
, &psd
);
4655 if (err
!= ERROR_SUCCESS
)
4661 static PSECURITY_DESCRIPTOR
4662 get_file_security_desc_by_name (const char *fname
)
4664 PSECURITY_DESCRIPTOR psd
= NULL
;
4666 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4667 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4669 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4671 err
= GetLastError ();
4672 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4676 psd
= xmalloc (sd_len
);
4677 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4689 unsigned n_subauthorities
;
4691 /* Use the last sub-authority value of the RID, the relative
4692 portion of the SID, as user/group ID. */
4693 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4694 if (n_subauthorities
< 1)
4695 return 0; /* the "World" RID */
4696 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4699 /* Caching SID and account values for faster lokup. */
4703 struct w32_id
*next
;
4705 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4708 static struct w32_id
*w32_idlist
;
4711 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4713 struct w32_id
*tail
, *found
;
4715 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4717 if (equal_sid ((PSID
)tail
->sid
, sid
))
4726 strcpy (name
, found
->name
);
4734 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4737 struct w32_id
*new_entry
;
4739 /* We don't want to leave behind stale cache from when Emacs was
4743 sid_len
= get_length_sid (sid
);
4744 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4747 new_entry
->rid
= id
;
4748 strcpy (new_entry
->name
, name
);
4749 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4750 new_entry
->next
= w32_idlist
;
4751 w32_idlist
= new_entry
;
4760 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4764 SID_NAME_USE ignore
;
4766 DWORD name_len
= sizeof (name
);
4768 DWORD domain_len
= sizeof (domain
);
4773 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4774 else if (what
== GID
)
4775 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4779 if (!result
|| !is_valid_sid (sid
))
4781 else if (!w32_cached_id (sid
, id
, nm
))
4783 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4784 domain
, &domain_len
, &ignore
)
4785 || name_len
> UNLEN
+1)
4789 *id
= get_rid (sid
);
4791 w32_add_to_cache (sid
, *id
, name
);
4798 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4800 int dflt_usr
= 0, dflt_grp
= 0;
4809 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4811 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4814 /* Consider files to belong to current user/group, if we cannot get
4815 more accurate information. */
4818 st
->st_uid
= dflt_passwd
.pw_uid
;
4819 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4823 st
->st_gid
= dflt_passwd
.pw_gid
;
4824 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4828 /* Return non-zero if NAME is a potentially slow filesystem. */
4830 is_slow_fs (const char *name
)
4835 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4836 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4837 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4838 devtype
= GetDriveType (NULL
); /* use root of current drive */
4841 /* GetDriveType needs the root directory of the drive. */
4842 strncpy (drive_root
, name
, 2);
4843 drive_root
[2] = '\\';
4844 drive_root
[3] = '\0';
4845 devtype
= GetDriveType (drive_root
);
4847 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4850 /* If this is non-zero, the caller wants accurate information about
4851 file's owner and group, which could be expensive to get. dired.c
4852 uses this flag when needed for the job at hand. */
4853 int w32_stat_get_owner_group
;
4855 /* MSVC stat function can't cope with UNC names and has other bugs, so
4856 replace it with our own. This also allows us to calculate consistent
4857 inode values and owner/group without hacks in the main Emacs code,
4858 and support file names encoded in UTF-8. */
4861 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4863 char *name
, *save_name
, *r
;
4864 WIN32_FIND_DATAW wfd_w
;
4865 WIN32_FIND_DATAA wfd_a
;
4867 unsigned __int64 fake_inode
= 0;
4870 int rootdir
= FALSE
;
4871 PSECURITY_DESCRIPTOR psd
= NULL
;
4872 int is_a_symlink
= 0;
4873 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4874 DWORD access_rights
= 0;
4875 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4876 FILETIME ctime
, atime
, wtime
;
4877 wchar_t name_w
[MAX_PATH
];
4878 char name_a
[MAX_PATH
];
4880 if (path
== NULL
|| buf
== NULL
)
4886 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4887 /* Must be valid filename, no wild cards or other invalid
4889 if (strpbrk (name
, "*?|<>\""))
4895 len
= strlen (name
);
4896 /* Allocate 1 extra byte so that we could append a slash to a root
4897 directory, down below. */
4898 name
= strcpy (alloca (len
+ 2), name
);
4900 /* Avoid a somewhat costly call to is_symlink if the filesystem
4901 doesn't support symlinks. */
4902 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4903 is_a_symlink
= is_symlink (name
);
4905 /* Plan A: Open the file and get all the necessary information via
4906 the resulting handle. This solves several issues in one blow:
4908 . retrieves attributes for the target of a symlink, if needed
4909 . gets attributes of root directories and symlinks pointing to
4910 root directories, thus avoiding the need for special-casing
4911 these and detecting them by examining the file-name format
4912 . retrieves more accurate attributes (e.g., non-zero size for
4913 some directories, esp. directories that are junction points)
4914 . correctly resolves "c:/..", "/.." and similar file names
4915 . avoids run-time penalties for 99% of use cases
4917 Plan A is always tried first, unless the user asked not to (but
4918 if the file is a symlink and we need to follow links, we try Plan
4919 A even if the user asked not to).
4921 If Plan A fails, we go to Plan B (below), where various
4922 potentially expensive techniques must be used to handle "special"
4923 files such as UNC volumes etc. */
4924 if (!(NILP (Vw32_get_true_file_attributes
)
4925 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4926 /* Following symlinks requires getting the info by handle. */
4927 || (is_a_symlink
&& follow_symlinks
))
4929 BY_HANDLE_FILE_INFORMATION info
;
4931 if (is_a_symlink
&& !follow_symlinks
)
4932 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4933 /* READ_CONTROL access rights are required to get security info
4934 by handle. But if the OS doesn't support security in the
4935 first place, we don't need to try. */
4936 if (is_windows_9x () != TRUE
)
4937 access_rights
|= READ_CONTROL
;
4939 if (w32_unicode_filenames
)
4941 filename_to_utf16 (name
, name_w
);
4942 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4944 /* If CreateFile fails with READ_CONTROL, try again with
4945 zero as access rights. */
4946 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4947 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4952 filename_to_ansi (name
, name_a
);
4953 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4955 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4956 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4959 if (fh
== INVALID_HANDLE_VALUE
)
4960 goto no_true_file_attributes
;
4962 /* This is more accurate in terms of getting the correct number
4963 of links, but is quite slow (it is noticeable when Emacs is
4964 making a list of file name completions). */
4965 if (GetFileInformationByHandle (fh
, &info
))
4967 nlinks
= info
.nNumberOfLinks
;
4968 /* Might as well use file index to fake inode values, but this
4969 is not guaranteed to be unique unless we keep a handle open
4970 all the time (even then there are situations where it is
4971 not unique). Reputedly, there are at most 48 bits of info
4972 (on NTFS, presumably less on FAT). */
4973 fake_inode
= info
.nFileIndexHigh
;
4975 fake_inode
+= info
.nFileIndexLow
;
4976 serialnum
= info
.dwVolumeSerialNumber
;
4977 fs_high
= info
.nFileSizeHigh
;
4978 fs_low
= info
.nFileSizeLow
;
4979 ctime
= info
.ftCreationTime
;
4980 atime
= info
.ftLastAccessTime
;
4981 wtime
= info
.ftLastWriteTime
;
4982 fattrs
= info
.dwFileAttributes
;
4986 /* We don't go to Plan B here, because it's not clear that
4987 it's a good idea. The only known use case where
4988 CreateFile succeeds, but GetFileInformationByHandle fails
4989 (with ERROR_INVALID_FUNCTION) is for character devices
4990 such as NUL, PRN, etc. For these, switching to Plan B is
4991 a net loss, because we lose the character device
4992 attribute returned by GetFileType below (FindFirstFile
4993 doesn't set that bit in the attributes), and the other
4994 fields don't make sense for character devices anyway.
4995 Emacs doesn't really care for non-file entities in the
4996 context of l?stat, so neither do we. */
4998 /* w32err is assigned so one could put a breakpoint here and
4999 examine its value, when GetFileInformationByHandle
5001 DWORD w32err
= GetLastError ();
5005 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
5011 /* Test for a symlink before testing for a directory, since
5012 symlinks to directories have the directory bit set, but we
5013 don't want them to appear as directories. */
5014 if (is_a_symlink
&& !follow_symlinks
)
5015 buf
->st_mode
= S_IFLNK
;
5016 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5017 buf
->st_mode
= S_IFDIR
;
5020 DWORD ftype
= GetFileType (fh
);
5024 case FILE_TYPE_DISK
:
5025 buf
->st_mode
= S_IFREG
;
5027 case FILE_TYPE_PIPE
:
5028 buf
->st_mode
= S_IFIFO
;
5030 case FILE_TYPE_CHAR
:
5031 case FILE_TYPE_UNKNOWN
:
5033 buf
->st_mode
= S_IFCHR
;
5036 /* We produce the fallback owner and group data, based on the
5037 current user that runs Emacs, in the following cases:
5039 . caller didn't request owner and group info
5040 . this is Windows 9X
5041 . getting security by handle failed, and we need to produce
5042 information for the target of a symlink (this is better
5043 than producing a potentially misleading info about the
5046 If getting security by handle fails, and we don't need to
5047 resolve symlinks, we try getting security by name. */
5048 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5049 get_file_owner_and_group (NULL
, buf
);
5052 psd
= get_file_security_desc_by_handle (fh
);
5055 get_file_owner_and_group (psd
, buf
);
5058 else if (!(is_a_symlink
&& follow_symlinks
))
5060 psd
= get_file_security_desc_by_name (name
);
5061 get_file_owner_and_group (psd
, buf
);
5065 get_file_owner_and_group (NULL
, buf
);
5071 no_true_file_attributes
:
5072 /* Plan B: Either getting a handle on the file failed, or the
5073 caller explicitly asked us to not bother making this
5074 information more accurate.
5076 Implementation note: In Plan B, we never bother to resolve
5077 symlinks, even if we got here because we tried Plan A and
5078 failed. That's because, even if the caller asked for extra
5079 precision by setting Vw32_get_true_file_attributes to t,
5080 resolving symlinks requires acquiring a file handle to the
5081 symlink, which we already know will fail. And if the user
5082 did not ask for extra precision, resolving symlinks will fly
5083 in the face of that request, since the user then wants the
5084 lightweight version of the code. */
5085 rootdir
= (path
>= save_name
+ len
- 1
5086 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
5088 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
5089 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
5090 if (IS_DIRECTORY_SEP (r
[0])
5091 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
5094 /* Note: If NAME is a symlink to the root of a UNC volume
5095 (i.e. "\\SERVER"), we will not detect that here, and we will
5096 return data about the symlink as result of FindFirst below.
5097 This is unfortunate, but that marginal use case does not
5098 justify a call to chase_symlinks which would impose a penalty
5099 on all the other use cases. (We get here for symlinks to
5100 roots of UNC volumes because CreateFile above fails for them,
5101 unlike with symlinks to root directories X:\ of drives.) */
5102 if (is_unc_volume (name
))
5104 fattrs
= unc_volume_file_attributes (name
);
5108 ctime
= atime
= wtime
= utc_base_ft
;
5112 /* Make sure root directories end in a slash. */
5113 if (!IS_DIRECTORY_SEP (name
[len
-1]))
5114 strcpy (name
+ len
, "\\");
5115 if (GetDriveType (name
) < 2)
5121 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
5122 ctime
= atime
= wtime
= utc_base_ft
;
5128 /* Make sure non-root directories do NOT end in a slash,
5129 otherwise FindFirstFile might fail. */
5130 if (IS_DIRECTORY_SEP (name
[len
-1]))
5133 /* (This is hacky, but helps when doing file completions on
5134 network drives.) Optimize by using information available from
5135 active readdir if possible. */
5136 len
= strlen (dir_pathname
);
5137 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5139 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5140 && last_dir_find_data
!= -1
5141 && !(is_a_symlink
&& follow_symlinks
)
5142 /* The 2 file-name comparisons below support only ASCII
5143 characters, and will lose (compare not equal) when
5144 the file names include non-ASCII characters that are
5145 the same but for the case. However, doing this
5146 properly involves: (a) converting both file names to
5147 UTF-16, (b) lower-casing both names using CharLowerW,
5148 and (c) comparing the results; this would be quite a
5149 bit slower, whereas Plan B is for users who want
5150 lightweight albeit inaccurate version of 'stat'. */
5151 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5152 && IS_DIRECTORY_SEP (name
[len
])
5153 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5155 have_wfd
= last_dir_find_data
;
5156 /* This was the last entry returned by readdir. */
5157 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5158 wfd_w
= dir_find_data_w
;
5160 wfd_a
= dir_find_data_a
;
5164 logon_network_drive (name
);
5166 if (w32_unicode_filenames
)
5168 filename_to_utf16 (name
, name_w
);
5169 fh
= FindFirstFileW (name_w
, &wfd_w
);
5170 have_wfd
= DIR_FIND_DATA_W
;
5174 filename_to_ansi (name
, name_a
);
5175 /* If NAME includes characters not representable by
5176 the current ANSI codepage, filename_to_ansi
5177 usually replaces them with a '?'. We don't want
5178 to let FindFirstFileA interpret those as wildcards,
5179 and "succeed", returning us data from some random
5180 file in the same directory. */
5181 if (_mbspbrk (name_a
, "?"))
5182 fh
= INVALID_HANDLE_VALUE
;
5184 fh
= FindFirstFileA (name_a
, &wfd_a
);
5185 have_wfd
= DIR_FIND_DATA_A
;
5187 if (fh
== INVALID_HANDLE_VALUE
)
5194 /* Note: if NAME is a symlink, the information we get from
5195 FindFirstFile is for the symlink, not its target. */
5196 if (have_wfd
== DIR_FIND_DATA_W
)
5198 fattrs
= wfd_w
.dwFileAttributes
;
5199 ctime
= wfd_w
.ftCreationTime
;
5200 atime
= wfd_w
.ftLastAccessTime
;
5201 wtime
= wfd_w
.ftLastWriteTime
;
5202 fs_high
= wfd_w
.nFileSizeHigh
;
5203 fs_low
= wfd_w
.nFileSizeLow
;
5207 fattrs
= wfd_a
.dwFileAttributes
;
5208 ctime
= wfd_a
.ftCreationTime
;
5209 atime
= wfd_a
.ftLastAccessTime
;
5210 wtime
= wfd_a
.ftLastWriteTime
;
5211 fs_high
= wfd_a
.nFileSizeHigh
;
5212 fs_low
= wfd_a
.nFileSizeLow
;
5216 serialnum
= volume_info
.serialnum
;
5218 if (is_a_symlink
&& !follow_symlinks
)
5219 buf
->st_mode
= S_IFLNK
;
5220 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5221 buf
->st_mode
= S_IFDIR
;
5223 buf
->st_mode
= S_IFREG
;
5225 get_file_owner_and_group (NULL
, buf
);
5228 buf
->st_ino
= fake_inode
;
5230 buf
->st_dev
= serialnum
;
5231 buf
->st_rdev
= serialnum
;
5233 buf
->st_size
= fs_high
;
5234 buf
->st_size
<<= 32;
5235 buf
->st_size
+= fs_low
;
5236 buf
->st_nlink
= nlinks
;
5238 /* Convert timestamps to Unix format. */
5239 buf
->st_mtime
= convert_time (wtime
);
5240 buf
->st_atime
= convert_time (atime
);
5241 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5242 buf
->st_ctime
= convert_time (ctime
);
5243 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5245 /* determine rwx permissions */
5246 if (is_a_symlink
&& !follow_symlinks
)
5247 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5250 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5251 permission
= S_IREAD
;
5253 permission
= S_IREAD
| S_IWRITE
;
5255 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5256 permission
|= S_IEXEC
;
5257 else if (is_exec (name
))
5258 permission
|= S_IEXEC
;
5261 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5267 stat (const char * path
, struct stat
* buf
)
5269 return stat_worker (path
, buf
, 1);
5273 lstat (const char * path
, struct stat
* buf
)
5275 return stat_worker (path
, buf
, 0);
5279 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5281 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5282 This is good enough for the current usage in Emacs, but is fragile.
5284 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5285 Gnulib does this and can serve as a model. */
5286 char fullname
[MAX_UTF8_PATH
];
5290 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5292 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5293 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5296 errno
= ENAMETOOLONG
;
5302 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5305 /* Provide fstat and utime as well as stat for consistent handling of
5308 fstat (int desc
, struct stat
* buf
)
5310 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5311 BY_HANDLE_FILE_INFORMATION info
;
5312 unsigned __int64 fake_inode
;
5315 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5317 case FILE_TYPE_DISK
:
5318 buf
->st_mode
= S_IFREG
;
5319 if (!GetFileInformationByHandle (fh
, &info
))
5325 case FILE_TYPE_PIPE
:
5326 buf
->st_mode
= S_IFIFO
;
5328 case FILE_TYPE_CHAR
:
5329 case FILE_TYPE_UNKNOWN
:
5331 buf
->st_mode
= S_IFCHR
;
5333 memset (&info
, 0, sizeof (info
));
5334 info
.dwFileAttributes
= 0;
5335 info
.ftCreationTime
= utc_base_ft
;
5336 info
.ftLastAccessTime
= utc_base_ft
;
5337 info
.ftLastWriteTime
= utc_base_ft
;
5340 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5341 buf
->st_mode
= S_IFDIR
;
5343 buf
->st_nlink
= info
.nNumberOfLinks
;
5344 /* Might as well use file index to fake inode values, but this
5345 is not guaranteed to be unique unless we keep a handle open
5346 all the time (even then there are situations where it is
5347 not unique). Reputedly, there are at most 48 bits of info
5348 (on NTFS, presumably less on FAT). */
5349 fake_inode
= info
.nFileIndexHigh
;
5351 fake_inode
+= info
.nFileIndexLow
;
5353 /* MSVC defines _ino_t to be short; other libc's might not. */
5354 if (sizeof (buf
->st_ino
) == 2)
5355 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5357 buf
->st_ino
= fake_inode
;
5359 /* If the caller so requested, get the true file owner and group.
5360 Otherwise, consider the file to belong to the current user. */
5361 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5362 get_file_owner_and_group (NULL
, buf
);
5365 PSECURITY_DESCRIPTOR psd
= NULL
;
5367 psd
= get_file_security_desc_by_handle (fh
);
5370 get_file_owner_and_group (psd
, buf
);
5374 get_file_owner_and_group (NULL
, buf
);
5377 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5378 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5380 buf
->st_size
= info
.nFileSizeHigh
;
5381 buf
->st_size
<<= 32;
5382 buf
->st_size
+= info
.nFileSizeLow
;
5384 /* Convert timestamps to Unix format. */
5385 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5386 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5387 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5388 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5389 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5391 /* determine rwx permissions */
5392 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5393 permission
= S_IREAD
;
5395 permission
= S_IREAD
| S_IWRITE
;
5397 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5398 permission
|= S_IEXEC
;
5401 #if 0 /* no way of knowing the filename */
5402 char * p
= strrchr (name
, '.');
5404 (xstrcasecmp (p
, ".exe") == 0 ||
5405 xstrcasecmp (p
, ".com") == 0 ||
5406 xstrcasecmp (p
, ".bat") == 0 ||
5407 xstrcasecmp (p
, ".cmd") == 0))
5408 permission
|= S_IEXEC
;
5412 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5417 /* A version of 'utime' which handles directories as well as
5421 utime (const char *name
, struct utimbuf
*times
)
5423 struct utimbuf deftime
;
5430 deftime
.modtime
= deftime
.actime
= time (NULL
);
5434 if (w32_unicode_filenames
)
5436 wchar_t name_utf16
[MAX_PATH
];
5438 if (filename_to_utf16 (name
, name_utf16
) != 0)
5439 return -1; /* errno set by filename_to_utf16 */
5441 /* Need write access to set times. */
5442 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5443 /* If NAME specifies a directory, FILE_SHARE_DELETE
5444 allows other processes to delete files inside it,
5445 while we have the directory open. */
5446 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5447 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5451 char name_ansi
[MAX_PATH
];
5453 if (filename_to_ansi (name
, name_ansi
) != 0)
5454 return -1; /* errno set by filename_to_ansi */
5456 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5457 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5458 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5460 if (fh
!= INVALID_HANDLE_VALUE
)
5462 convert_from_time_t (times
->actime
, &atime
);
5463 convert_from_time_t (times
->modtime
, &mtime
);
5464 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5474 DWORD err
= GetLastError ();
5478 case ERROR_FILE_NOT_FOUND
:
5479 case ERROR_PATH_NOT_FOUND
:
5480 case ERROR_INVALID_DRIVE
:
5481 case ERROR_BAD_NETPATH
:
5482 case ERROR_DEV_NOT_EXIST
:
5483 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5484 file name includes ?s, i.e. translation to ANSI failed. */
5485 case ERROR_INVALID_NAME
:
5488 case ERROR_TOO_MANY_OPEN_FILES
:
5491 case ERROR_ACCESS_DENIED
:
5492 case ERROR_SHARING_VIOLATION
:
5505 sys_umask (int mode
)
5507 static int current_mask
;
5508 int retval
, arg
= 0;
5510 /* The only bit we really support is the write bit. Files are
5511 always readable on MS-Windows, and the execute bit does not exist
5513 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5514 to prevent access by other users on NTFS. */
5515 if ((mode
& S_IWRITE
) != 0)
5518 retval
= _umask (arg
);
5519 /* Merge into the return value the bits they've set the last time,
5520 which msvcrt.dll ignores and never returns. Emacs insists on its
5521 notion of mask being identical to what we return. */
5522 retval
|= (current_mask
& ~S_IWRITE
);
5523 current_mask
= mode
;
5529 /* Symlink-related functions. */
5530 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5531 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5535 symlink (char const *filename
, char const *linkname
)
5537 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5539 int dir_access
, filename_ends_in_slash
;
5541 /* Diagnostics follows Posix as much as possible. */
5542 if (filename
== NULL
|| linkname
== NULL
)
5552 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5554 errno
= ENAMETOOLONG
;
5558 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5559 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5565 /* Note: since empty FILENAME was already rejected, we can safely
5566 refer to FILENAME[1]. */
5567 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5569 /* Non-absolute FILENAME is understood as being relative to
5570 LINKNAME's directory. We need to prepend that directory to
5571 FILENAME to get correct results from faccessat below, since
5572 otherwise it will interpret FILENAME relative to the
5573 directory where the Emacs process runs. Note that
5574 make-symbolic-link always makes sure LINKNAME is a fully
5575 expanded file name. */
5576 char tem
[MAX_UTF8_PATH
];
5577 char *p
= linkfn
+ strlen (linkfn
);
5579 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5582 strncpy (tem
, linkfn
, p
- linkfn
);
5583 strcpy (tem
+ (p
- linkfn
), filename
);
5584 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5587 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5589 /* Since Windows distinguishes between symlinks to directories and
5590 to files, we provide a kludgy feature: if FILENAME doesn't
5591 exist, but ends in a slash, we create a symlink to directory. If
5592 FILENAME exists and is a directory, we always create a symlink to
5594 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5595 if (dir_access
== 0 || filename_ends_in_slash
)
5596 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5598 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5599 if (filename_ends_in_slash
)
5600 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5603 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5605 /* ENOSYS is set by create_symbolic_link, when it detects that
5606 the OS doesn't support the CreateSymbolicLink API. */
5607 if (errno
!= ENOSYS
)
5609 DWORD w32err
= GetLastError ();
5613 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5614 TGTFN point to the same file name, go figure. */
5616 case ERROR_FILE_EXISTS
:
5619 case ERROR_ACCESS_DENIED
:
5622 case ERROR_FILE_NOT_FOUND
:
5623 case ERROR_PATH_NOT_FOUND
:
5624 case ERROR_BAD_NETPATH
:
5625 case ERROR_INVALID_REPARSE_DATA
:
5628 case ERROR_DIRECTORY
:
5631 case ERROR_PRIVILEGE_NOT_HELD
:
5632 case ERROR_NOT_ALL_ASSIGNED
:
5635 case ERROR_DISK_FULL
:
5648 /* A quick inexpensive test of whether FILENAME identifies a file that
5649 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5650 must already be in the normalized form returned by
5651 map_w32_filename. If the symlink is to a directory, the
5652 FILE_ATTRIBUTE_DIRECTORY bit will be set in the return value.
5654 Note: for repeated operations on many files, it is best to test
5655 whether the underlying volume actually supports symlinks, by
5656 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5657 avoid the call to this function if it doesn't. That's because the
5658 call to GetFileAttributes takes a non-negligible time, especially
5659 on non-local or removable filesystems. See stat_worker for an
5660 example of how to do that. */
5662 is_symlink (const char *filename
)
5665 wchar_t filename_w
[MAX_PATH
];
5666 char filename_a
[MAX_PATH
];
5667 WIN32_FIND_DATAW wfdw
;
5668 WIN32_FIND_DATAA wfda
;
5670 int attrs_mean_symlink
;
5672 if (w32_unicode_filenames
)
5674 filename_to_utf16 (filename
, filename_w
);
5675 attrs
= GetFileAttributesW (filename_w
);
5679 filename_to_ansi (filename
, filename_a
);
5680 attrs
= GetFileAttributesA (filename_a
);
5684 DWORD w32err
= GetLastError ();
5688 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5690 case ERROR_ACCESS_DENIED
:
5693 case ERROR_FILE_NOT_FOUND
:
5694 case ERROR_PATH_NOT_FOUND
:
5701 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5703 logon_network_drive (filename
);
5704 if (w32_unicode_filenames
)
5706 fh
= FindFirstFileW (filename_w
, &wfdw
);
5707 attrs_mean_symlink
=
5708 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5709 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5710 if (attrs_mean_symlink
)
5711 attrs_mean_symlink
|= (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5713 else if (_mbspbrk (filename_a
, "?"))
5715 /* filename_to_ansi failed to convert the file name. */
5721 fh
= FindFirstFileA (filename_a
, &wfda
);
5722 attrs_mean_symlink
=
5723 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5724 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5725 if (attrs_mean_symlink
)
5726 attrs_mean_symlink
|= (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
);
5728 if (fh
== INVALID_HANDLE_VALUE
)
5731 return attrs_mean_symlink
;
5734 /* If NAME identifies a symbolic link, copy into BUF the file name of
5735 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5736 null-terminate the target name, even if it fits. Return the number
5737 of bytes copied, or -1 if NAME is not a symlink or any error was
5738 encountered while resolving it. The file name copied into BUF is
5739 encoded in the current ANSI codepage. */
5741 readlink (const char *name
, char *buf
, size_t buf_size
)
5744 TOKEN_PRIVILEGES privs
;
5745 int restore_privs
= 0;
5748 char resolved
[MAX_UTF8_PATH
];
5761 path
= map_w32_filename (name
, NULL
);
5763 if (strlen (path
) > MAX_UTF8_PATH
)
5765 errno
= ENAMETOOLONG
;
5770 if (is_windows_9x () == TRUE
5771 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5772 || !is_symlink (path
))
5775 errno
= EINVAL
; /* not a symlink */
5779 /* Done with simple tests, now we're in for some _real_ work. */
5780 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5782 /* Implementation note: From here and onward, don't return early,
5783 since that will fail to restore the original set of privileges of
5784 the calling thread. */
5786 retval
= -1; /* not too optimistic, are we? */
5788 /* Note: In the next call to CreateFile, we use zero as the 2nd
5789 argument because, when the symlink is a hidden/system file,
5790 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5791 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5792 and directory symlinks. */
5793 if (w32_unicode_filenames
)
5795 wchar_t path_w
[MAX_PATH
];
5797 filename_to_utf16 (path
, path_w
);
5798 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5799 FILE_FLAG_OPEN_REPARSE_POINT
5800 | FILE_FLAG_BACKUP_SEMANTICS
,
5805 char path_a
[MAX_PATH
];
5807 filename_to_ansi (path
, path_a
);
5808 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5809 FILE_FLAG_OPEN_REPARSE_POINT
5810 | FILE_FLAG_BACKUP_SEMANTICS
,
5813 if (sh
!= INVALID_HANDLE_VALUE
)
5815 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5816 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5819 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5820 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5823 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5827 /* Copy the link target name, in wide characters, from
5828 reparse_data, then convert it to multibyte encoding in
5829 the current locale's codepage. */
5833 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5835 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5836 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5837 size_t size_to_copy
= buf_size
;
5839 /* According to MSDN, PrintNameLength does not include the
5840 terminating null character. */
5841 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5842 memcpy (lwname
, lwname_src
, lwname_len
);
5843 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5844 filename_from_utf16 (lwname
, resolved
);
5845 dostounix_filename (resolved
);
5846 lname_size
= strlen (resolved
) + 1;
5847 if (lname_size
<= buf_size
)
5848 size_to_copy
= lname_size
;
5849 strncpy (buf
, resolved
, size_to_copy
);
5851 retval
= size_to_copy
;
5857 /* CreateFile failed. */
5858 DWORD w32err2
= GetLastError ();
5862 case ERROR_FILE_NOT_FOUND
:
5863 case ERROR_PATH_NOT_FOUND
:
5866 case ERROR_ACCESS_DENIED
:
5867 case ERROR_TOO_MANY_OPEN_FILES
:
5877 restore_privilege (&privs
);
5885 readlinkat (int fd
, char const *name
, char *buffer
,
5888 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5889 as in fstatat. FIXME: Add proper support for readlinkat. */
5890 char fullname
[MAX_UTF8_PATH
];
5894 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5897 errno
= ENAMETOOLONG
;
5903 return readlink (name
, buffer
, buffer_size
);
5906 /* If FILE is a symlink, return its target (stored in a static
5907 buffer); otherwise return FILE.
5909 This function repeatedly resolves symlinks in the last component of
5910 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5911 until it arrives at a file whose last component is not a symlink,
5912 or some error occurs. It returns the target of the last
5913 successfully resolved symlink in the chain. If it succeeds to
5914 resolve even a single symlink, the value returned is an absolute
5915 file name with backslashes (result of GetFullPathName). By
5916 contrast, if the original FILE is returned, it is unaltered.
5918 Note: This function can set errno even if it succeeds.
5920 Implementation note: we only resolve the last portion ("basename")
5921 of the argument FILE and of each following file in the chain,
5922 disregarding any possible symlinks in its leading directories.
5923 This is because Windows system calls and library functions
5924 transparently resolve symlinks in leading directories and return
5925 correct information, as long as the basename is not a symlink. */
5927 chase_symlinks (const char *file
)
5929 static char target
[MAX_UTF8_PATH
];
5930 char link
[MAX_UTF8_PATH
];
5931 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5932 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5933 ssize_t res
, link_len
;
5936 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5937 return (char *)file
;
5939 if (w32_unicode_filenames
)
5941 wchar_t file_w
[MAX_PATH
];
5943 filename_to_utf16 (file
, file_w
);
5944 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5945 return (char *)file
;
5946 filename_from_utf16 (link_w
, link
);
5950 char file_a
[MAX_PATH
];
5952 filename_to_ansi (file
, file_a
);
5953 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5954 return (char *)file
;
5955 filename_from_ansi (link_a
, link
);
5957 link_len
= strlen (link
);
5962 /* Remove trailing slashes, as we want to resolve the last
5963 non-trivial part of the link name. */
5964 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5965 link
[link_len
--] = '\0';
5967 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5971 if (!(IS_DEVICE_SEP (target
[1])
5972 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5974 /* Target is relative. Append it to the directory part of
5975 the symlink, then copy the result back to target. */
5976 char *p
= link
+ link_len
;
5978 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5981 strcpy (target
, link
);
5983 /* Resolve any "." and ".." to get a fully-qualified file name
5985 if (w32_unicode_filenames
)
5987 filename_to_utf16 (target
, target_w
);
5988 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5990 filename_from_utf16 (link_w
, link
);
5994 filename_to_ansi (target
, target_a
);
5995 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5997 filename_from_ansi (link_a
, link
);
5999 link_len
= strlen (link
);
6001 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
6003 if (loop_count
> 100)
6006 if (target
[0] == '\0') /* not a single call to readlink succeeded */
6007 return (char *)file
;
6012 /* Posix ACL emulation. */
6015 acl_valid (acl_t acl
)
6017 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
6021 acl_to_text (acl_t acl
, ssize_t
*size
)
6024 SECURITY_INFORMATION flags
=
6025 OWNER_SECURITY_INFORMATION
|
6026 GROUP_SECURITY_INFORMATION
|
6027 DACL_SECURITY_INFORMATION
;
6028 char *retval
= NULL
;
6034 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
6037 /* We don't want to mix heaps, so we duplicate the string in our
6038 heap and free the one allocated by the API. */
6039 retval
= xstrdup (str_acl
);
6042 LocalFree (str_acl
);
6044 else if (errno
!= ENOTSUP
)
6051 acl_from_text (const char *acl_str
)
6053 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
6059 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
6062 retval
= xmalloc (sd_size
);
6063 memcpy (retval
, psd
, sd_size
);
6066 else if (errno
!= ENOTSUP
)
6073 acl_free (void *ptr
)
6080 acl_get_file (const char *fname
, acl_type_t type
)
6082 PSECURITY_DESCRIPTOR psd
= NULL
;
6083 const char *filename
;
6085 if (type
== ACL_TYPE_ACCESS
)
6088 SECURITY_INFORMATION si
=
6089 OWNER_SECURITY_INFORMATION
|
6090 GROUP_SECURITY_INFORMATION
|
6091 DACL_SECURITY_INFORMATION
;
6094 filename
= map_w32_filename (fname
, NULL
);
6095 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6096 fname
= chase_symlinks (filename
);
6101 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
6102 && errno
!= ENOTSUP
)
6104 err
= GetLastError ();
6105 if (err
== ERROR_INSUFFICIENT_BUFFER
)
6107 psd
= xmalloc (sd_len
);
6108 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
6115 else if (err
== ERROR_FILE_NOT_FOUND
6116 || err
== ERROR_PATH_NOT_FOUND
6117 /* ERROR_INVALID_NAME is what we get if
6118 w32-unicode-filenames is nil and the file cannot
6119 be encoded in the current ANSI codepage. */
6120 || err
== ERROR_INVALID_NAME
)
6128 else if (type
!= ACL_TYPE_DEFAULT
)
6135 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6137 TOKEN_PRIVILEGES old1
, old2
;
6139 int st
= 0, retval
= -1;
6140 SECURITY_INFORMATION flags
= 0;
6141 PSID psidOwner
, psidGroup
;
6146 const char *filename
;
6148 if (acl_valid (acl
) != 0
6149 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6155 if (type
== ACL_TYPE_DEFAULT
)
6161 filename
= map_w32_filename (fname
, NULL
);
6162 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6163 fname
= chase_symlinks (filename
);
6167 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6170 flags
|= OWNER_SECURITY_INFORMATION
;
6171 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6174 flags
|= GROUP_SECURITY_INFORMATION
;
6175 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6178 flags
|= DACL_SECURITY_INFORMATION
;
6182 /* According to KB-245153, setting the owner will succeed if either:
6183 (1) the caller is the user who will be the new owner, and has the
6184 SE_TAKE_OWNERSHIP privilege, or
6185 (2) the caller has the SE_RESTORE privilege, in which case she can
6186 set any valid user or group as the owner
6188 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6189 privileges, and disregard any failures in obtaining them. If
6190 these privileges cannot be obtained, and do not already exist in
6191 the calling thread's security token, this function could fail
6193 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6195 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6200 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6201 DACL inheritance is involved, but it seems to preserve ownership
6202 better than SetNamedSecurityInfo, which is important e.g., in
6204 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6206 err
= GetLastError ();
6208 if (errno
!= ENOTSUP
)
6209 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6210 psidOwner
, psidGroup
, pacl
, NULL
);
6213 err
= ERROR_SUCCESS
;
6214 if (err
!= ERROR_SUCCESS
)
6216 if (errno
== ENOTSUP
)
6218 else if (err
== ERROR_INVALID_OWNER
6219 || err
== ERROR_NOT_ALL_ASSIGNED
6220 || err
== ERROR_ACCESS_DENIED
)
6222 /* Maybe the requested ACL and the one the file already has
6223 are identical, in which case we can silently ignore the
6224 failure. (And no, Windows doesn't.) */
6225 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6230 char *acl_from
= acl_to_text (current_acl
, NULL
);
6231 char *acl_to
= acl_to_text (acl
, NULL
);
6233 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6239 acl_free (acl_from
);
6242 acl_free (current_acl
);
6245 else if (err
== ERROR_FILE_NOT_FOUND
6246 || err
== ERROR_PATH_NOT_FOUND
6247 /* ERROR_INVALID_NAME is what we get if
6248 w32-unicode-filenames is nil and the file cannot be
6249 encoded in the current ANSI codepage. */
6250 || err
== ERROR_INVALID_NAME
)
6264 restore_privilege (&old2
);
6265 restore_privilege (&old1
);
6273 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6274 have a fixed max size for file names, so we don't need the kind of
6275 alloc/malloc/realloc dance the gnulib version does. We also don't
6276 support FD-relative symlinks. */
6278 careadlinkat (int fd
, char const *filename
,
6279 char *buffer
, size_t buffer_size
,
6280 struct allocator
const *alloc
,
6281 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6283 char linkname
[MAX_UTF8_PATH
];
6286 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6290 char *retval
= buffer
;
6292 linkname
[link_size
++] = '\0';
6293 if (link_size
> buffer_size
)
6294 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6296 memcpy (retval
, linkname
, link_size
);
6304 w32_copy_file (const char *from
, const char *to
,
6305 int keep_time
, int preserve_ownership
, int copy_acls
)
6309 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6310 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6312 /* We ignore preserve_ownership for now. */
6313 preserve_ownership
= preserve_ownership
;
6317 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6318 if (acl
== NULL
&& acl_errno_valid (errno
))
6321 if (w32_unicode_filenames
)
6323 filename_to_utf16 (from
, from_w
);
6324 filename_to_utf16 (to
, to_w
);
6325 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6329 filename_to_ansi (from
, from_a
);
6330 filename_to_ansi (to
, to_a
);
6331 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6335 /* CopyFile doesn't set errno when it fails. By far the most
6336 "popular" reason is that the target is read-only. */
6337 DWORD err
= GetLastError ();
6341 case ERROR_FILE_NOT_FOUND
:
6344 case ERROR_ACCESS_DENIED
:
6347 case ERROR_ENCRYPTION_FAILED
:
6359 /* CopyFile retains the timestamp by default. However, see
6360 "Community Additions" for CopyFile: it sounds like that is not
6361 entirely true. Testing on Windows XP confirms that modified time
6362 is copied, but creation and last-access times are not.
6364 else if (!keep_time
)
6366 struct timespec now
;
6369 if (w32_unicode_filenames
)
6371 /* Ensure file is writable while its times are set. */
6372 attributes
= GetFileAttributesW (to_w
);
6373 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6374 now
= current_timespec ();
6375 if (set_file_times (-1, to
, now
, now
))
6377 /* Restore original attributes. */
6378 SetFileAttributesW (to_w
, attributes
);
6383 /* Restore original attributes. */
6384 SetFileAttributesW (to_w
, attributes
);
6388 attributes
= GetFileAttributesA (to_a
);
6389 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6390 now
= current_timespec ();
6391 if (set_file_times (-1, to
, now
, now
))
6393 SetFileAttributesA (to_a
, attributes
);
6398 SetFileAttributesA (to_a
, attributes
);
6404 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6406 if (fail
&& acl_errno_valid (errno
))
6414 /* Support for browsing other processes and their attributes. See
6415 process.c for the Lisp bindings. */
6417 /* Helper wrapper functions. */
6419 static HANDLE WINAPI
6420 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6422 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6424 if (g_b_init_create_toolhelp32_snapshot
== 0)
6426 g_b_init_create_toolhelp32_snapshot
= 1;
6427 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6428 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6429 "CreateToolhelp32Snapshot");
6431 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6433 return INVALID_HANDLE_VALUE
;
6435 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6439 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6441 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6443 if (g_b_init_process32_first
== 0)
6445 g_b_init_process32_first
= 1;
6446 s_pfn_Process32_First
= (Process32First_Proc
)
6447 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6450 if (s_pfn_Process32_First
== NULL
)
6454 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6458 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6460 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6462 if (g_b_init_process32_next
== 0)
6464 g_b_init_process32_next
= 1;
6465 s_pfn_Process32_Next
= (Process32Next_Proc
)
6466 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6469 if (s_pfn_Process32_Next
== NULL
)
6473 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6477 open_thread_token (HANDLE ThreadHandle
,
6478 DWORD DesiredAccess
,
6480 PHANDLE TokenHandle
)
6482 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6483 HMODULE hm_advapi32
= NULL
;
6484 if (is_windows_9x () == TRUE
)
6486 SetLastError (ERROR_NOT_SUPPORTED
);
6489 if (g_b_init_open_thread_token
== 0)
6491 g_b_init_open_thread_token
= 1;
6492 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6493 s_pfn_Open_Thread_Token
=
6494 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6496 if (s_pfn_Open_Thread_Token
== NULL
)
6498 SetLastError (ERROR_NOT_SUPPORTED
);
6502 s_pfn_Open_Thread_Token (
6511 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6513 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6514 HMODULE hm_advapi32
= NULL
;
6515 if (is_windows_9x () == TRUE
)
6519 if (g_b_init_impersonate_self
== 0)
6521 g_b_init_impersonate_self
= 1;
6522 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6523 s_pfn_Impersonate_Self
=
6524 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6526 if (s_pfn_Impersonate_Self
== NULL
)
6530 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6534 revert_to_self (void)
6536 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6537 HMODULE hm_advapi32
= NULL
;
6538 if (is_windows_9x () == TRUE
)
6542 if (g_b_init_revert_to_self
== 0)
6544 g_b_init_revert_to_self
= 1;
6545 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6546 s_pfn_Revert_To_Self
=
6547 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6549 if (s_pfn_Revert_To_Self
== NULL
)
6553 return s_pfn_Revert_To_Self ();
6557 get_process_memory_info (HANDLE h_proc
,
6558 PPROCESS_MEMORY_COUNTERS mem_counters
,
6561 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6562 HMODULE hm_psapi
= NULL
;
6563 if (is_windows_9x () == TRUE
)
6567 if (g_b_init_get_process_memory_info
== 0)
6569 g_b_init_get_process_memory_info
= 1;
6570 hm_psapi
= LoadLibrary ("Psapi.dll");
6572 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6573 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6575 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6579 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6583 get_process_working_set_size (HANDLE h_proc
,
6587 static GetProcessWorkingSetSize_Proc
6588 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6590 if (is_windows_9x () == TRUE
)
6594 if (g_b_init_get_process_working_set_size
== 0)
6596 g_b_init_get_process_working_set_size
= 1;
6597 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6598 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6599 "GetProcessWorkingSetSize");
6601 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6605 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6609 global_memory_status (MEMORYSTATUS
*buf
)
6611 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6613 if (is_windows_9x () == TRUE
)
6617 if (g_b_init_global_memory_status
== 0)
6619 g_b_init_global_memory_status
= 1;
6620 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6621 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6622 "GlobalMemoryStatus");
6624 if (s_pfn_Global_Memory_Status
== NULL
)
6628 return s_pfn_Global_Memory_Status (buf
);
6632 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6634 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6636 if (is_windows_9x () == TRUE
)
6640 if (g_b_init_global_memory_status_ex
== 0)
6642 g_b_init_global_memory_status_ex
= 1;
6643 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6644 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6645 "GlobalMemoryStatusEx");
6647 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6651 return s_pfn_Global_Memory_Status_Ex (buf
);
6655 list_system_processes (void)
6657 Lisp_Object proclist
= Qnil
;
6660 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6662 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6664 PROCESSENTRY32 proc_entry
;
6668 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6669 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6670 res
= process32_next (h_snapshot
, &proc_entry
))
6672 proc_id
= proc_entry
.th32ProcessID
;
6673 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6676 CloseHandle (h_snapshot
);
6677 proclist
= Fnreverse (proclist
);
6684 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6686 TOKEN_PRIVILEGES priv
;
6687 DWORD priv_size
= sizeof (priv
);
6688 DWORD opriv_size
= sizeof (*old_priv
);
6689 HANDLE h_token
= NULL
;
6690 HANDLE h_thread
= GetCurrentThread ();
6694 res
= open_thread_token (h_thread
,
6695 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6697 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6699 if (impersonate_self (SecurityImpersonation
))
6700 res
= open_thread_token (h_thread
,
6701 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6706 priv
.PrivilegeCount
= 1;
6707 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6708 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6709 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6710 old_priv
, &opriv_size
)
6711 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6715 CloseHandle (h_token
);
6721 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6723 DWORD priv_size
= sizeof (*priv
);
6724 HANDLE h_token
= NULL
;
6727 if (open_thread_token (GetCurrentThread (),
6728 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6731 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6732 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6736 CloseHandle (h_token
);
6742 ltime (ULONGLONG time_100ns
)
6744 ULONGLONG time_sec
= time_100ns
/ 10000000;
6745 int subsec
= time_100ns
% 10000000;
6746 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6747 subsec
/ 10, subsec
% 10 * 100000);
6750 #define U64_TO_LISP_TIME(time) ltime (time)
6753 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6754 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6757 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6758 ULONGLONG tem1
, tem2
, tem3
, tem
;
6761 || !get_process_times_fn
6762 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6763 &ft_kernel
, &ft_user
))
6766 GetSystemTimeAsFileTime (&ft_current
);
6768 FILETIME_TO_U64 (tem1
, ft_kernel
);
6769 *stime
= U64_TO_LISP_TIME (tem1
);
6771 FILETIME_TO_U64 (tem2
, ft_user
);
6772 *utime
= U64_TO_LISP_TIME (tem2
);
6775 *ttime
= U64_TO_LISP_TIME (tem3
);
6777 FILETIME_TO_U64 (tem
, ft_creation
);
6778 /* Process no 4 (System) returns zero creation time. */
6781 *ctime
= U64_TO_LISP_TIME (tem
);
6785 FILETIME_TO_U64 (tem3
, ft_current
);
6786 tem
= (tem3
- utc_base
) - tem
;
6788 *etime
= U64_TO_LISP_TIME (tem
);
6792 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6803 system_process_attributes (Lisp_Object pid
)
6805 Lisp_Object attrs
= Qnil
;
6806 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6807 HANDLE h_snapshot
, h_proc
;
6810 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6811 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6812 DWORD glength
= sizeof (gname
);
6813 HANDLE token
= NULL
;
6814 SID_NAME_USE user_type
;
6815 unsigned char *buf
= NULL
;
6817 TOKEN_USER user_token
;
6818 TOKEN_PRIMARY_GROUP group_token
;
6821 PROCESS_MEMORY_COUNTERS mem
;
6822 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6823 SIZE_T minrss
, maxrss
;
6825 MEMORY_STATUS_EX memstex
;
6826 double totphys
= 0.0;
6827 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6829 BOOL result
= FALSE
;
6831 CHECK_NUMBER_OR_FLOAT (pid
);
6832 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6834 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6836 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6841 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6842 for (res
= process32_first (h_snapshot
, &pe
); res
;
6843 res
= process32_next (h_snapshot
, &pe
))
6845 if (proc_id
== pe
.th32ProcessID
)
6848 decoded_cmd
= build_string ("Idle");
6851 /* Decode the command name from locale-specific
6853 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6856 code_convert_string_norecord (cmd_str
,
6857 Vlocale_coding_system
, 0);
6859 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6860 attrs
= Fcons (Fcons (Qppid
,
6861 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6863 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6865 attrs
= Fcons (Fcons (Qthcount
,
6866 make_fixnum_or_float (pe
.cntThreads
)),
6873 CloseHandle (h_snapshot
);
6879 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6881 /* If we were denied a handle to the process, try again after
6882 enabling the SeDebugPrivilege in our process. */
6885 TOKEN_PRIVILEGES priv_current
;
6887 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6889 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6891 restore_privilege (&priv_current
);
6897 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6900 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6901 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6903 buf
= xmalloc (blen
);
6904 result
= get_token_information (token
, TokenUser
,
6905 (LPVOID
)buf
, blen
, &needed
);
6908 memcpy (&user_token
, buf
, sizeof (user_token
));
6909 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6911 euid
= get_rid (user_token
.User
.Sid
);
6912 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6917 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6920 strcpy (uname
, "unknown");
6924 ulength
= strlen (uname
);
6930 /* Determine a reasonable euid and gid values. */
6931 if (xstrcasecmp ("administrator", uname
) == 0)
6933 euid
= 500; /* well-known Administrator uid */
6934 egid
= 513; /* well-known None gid */
6938 /* Get group id and name. */
6939 result
= get_token_information (token
, TokenPrimaryGroup
,
6940 (LPVOID
)buf
, blen
, &needed
);
6941 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6943 buf
= xrealloc (buf
, blen
= needed
);
6944 result
= get_token_information (token
, TokenPrimaryGroup
,
6945 (LPVOID
)buf
, blen
, &needed
);
6949 memcpy (&group_token
, buf
, sizeof (group_token
));
6950 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6952 egid
= get_rid (group_token
.PrimaryGroup
);
6953 dlength
= sizeof (domain
);
6955 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6956 gname
, &glength
, NULL
, &dlength
,
6959 w32_add_to_cache (group_token
.PrimaryGroup
,
6963 strcpy (gname
, "None");
6967 glength
= strlen (gname
);
6975 if (!is_windows_9x ())
6977 /* We couldn't open the process token, presumably because of
6978 insufficient access rights. Assume this process is run
6980 strcpy (uname
, "SYSTEM");
6981 strcpy (gname
, "None");
6982 euid
= 18; /* SYSTEM */
6983 egid
= 513; /* None */
6984 glength
= strlen (gname
);
6985 ulength
= strlen (uname
);
6987 /* If we are running under Windows 9X, where security calls are
6988 not supported, we assume all processes are run by the current
6990 else if (GetUserName (uname
, &ulength
))
6992 if (xstrcasecmp ("administrator", uname
) == 0)
6997 strcpy (gname
, "None");
6998 glength
= strlen (gname
);
6999 ulength
= strlen (uname
);
7005 strcpy (uname
, "administrator");
7006 ulength
= strlen (uname
);
7007 strcpy (gname
, "None");
7008 glength
= strlen (gname
);
7011 CloseHandle (token
);
7014 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
7015 tem
= make_unibyte_string (uname
, ulength
);
7016 attrs
= Fcons (Fcons (Quser
,
7017 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7019 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
7020 tem
= make_unibyte_string (gname
, glength
);
7021 attrs
= Fcons (Fcons (Qgroup
,
7022 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
7025 if (global_memory_status_ex (&memstex
))
7026 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7027 totphys
= memstex
.ullTotalPhys
/ 1024.0;
7029 /* Visual Studio 6 cannot convert an unsigned __int64 type to
7030 double, so we need to do this for it... */
7032 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
7033 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
7034 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
7036 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
7038 #endif /* __GNUC__ || _MSC_VER >= 1300 */
7039 else if (global_memory_status (&memst
))
7040 totphys
= memst
.dwTotalPhys
/ 1024.0;
7043 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
7046 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7048 attrs
= Fcons (Fcons (Qmajflt
,
7049 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
7051 attrs
= Fcons (Fcons (Qvsize
,
7052 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
7054 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7056 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7059 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
7061 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
7063 attrs
= Fcons (Fcons (Qmajflt
,
7064 make_fixnum_or_float (mem
.PageFaultCount
)),
7066 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
7068 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7071 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
7073 DWORD rss
= maxrss
/ 1024;
7075 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
7077 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
7080 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
7082 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
7083 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
7084 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
7085 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
7086 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
7087 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
7090 /* FIXME: Retrieve command line by walking the PEB of the process. */
7093 CloseHandle (h_proc
);
7098 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
7099 unsigned long long *totalswap
, unsigned long long *freeswap
)
7102 MEMORY_STATUS_EX memstex
;
7104 /* Use GlobalMemoryStatusEx if available, as it can report more than
7106 if (global_memory_status_ex (&memstex
))
7108 *totalram
= memstex
.ullTotalPhys
;
7109 *freeram
= memstex
.ullAvailPhys
;
7110 *totalswap
= memstex
.ullTotalPageFile
;
7111 *freeswap
= memstex
.ullAvailPageFile
;
7114 else if (global_memory_status (&memst
))
7116 *totalram
= memst
.dwTotalPhys
;
7117 *freeram
= memst
.dwAvailPhys
;
7118 *totalswap
= memst
.dwTotalPageFile
;
7119 *freeswap
= memst
.dwAvailPageFile
;
7127 /* Wrappers for winsock functions to map between our file descriptors
7128 and winsock's handles; also set h_errno for convenience.
7130 To allow Emacs to run on systems which don't have winsock support
7131 installed, we dynamically link to winsock on startup if present, and
7132 otherwise provide the minimum necessary functionality
7133 (eg. gethostname). */
7135 /* function pointers for relevant socket functions */
7136 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7137 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7138 int (PASCAL
*pfn_WSAGetLastError
) (void);
7139 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7140 int (PASCAL
*pfn_WSAEnumNetworkEvents
) (SOCKET s
, HANDLE hEventObject
,
7141 WSANETWORKEVENTS
*NetworkEvents
);
7143 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7144 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7145 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7146 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7147 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7148 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7149 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7150 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7151 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7152 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7153 int (PASCAL
*pfn_WSACleanup
) (void);
7155 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7156 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7157 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7158 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7159 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7160 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7161 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7162 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7163 const char * optval
, int optlen
);
7164 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7165 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7167 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7168 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7169 struct sockaddr
* from
, int * fromlen
);
7170 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7171 const struct sockaddr
* to
, int tolen
);
7173 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7174 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7175 #ifndef HANDLE_FLAG_INHERIT
7176 #define HANDLE_FLAG_INHERIT 1
7180 static int winsock_inuse
;
7185 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7187 release_listen_threads ();
7188 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7189 after WSAStartup returns successfully, but it seems reasonable
7190 to allow unloading winsock anyway in that case. */
7191 if (pfn_WSACleanup () == 0 ||
7192 pfn_WSAGetLastError () == WSAENETDOWN
)
7194 if (FreeLibrary (winsock_lib
))
7203 init_winsock (int load_now
)
7205 WSADATA winsockData
;
7207 if (winsock_lib
!= NULL
)
7210 pfn_SetHandleInformation
7211 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7212 "SetHandleInformation");
7214 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7216 if (winsock_lib
!= NULL
)
7218 /* dynamically link to socket functions */
7220 #define LOAD_PROC(fn) \
7221 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7224 LOAD_PROC (WSAStartup
);
7225 LOAD_PROC (WSASetLastError
);
7226 LOAD_PROC (WSAGetLastError
);
7227 LOAD_PROC (WSAEventSelect
);
7228 LOAD_PROC (WSAEnumNetworkEvents
);
7229 LOAD_PROC (WSACreateEvent
);
7230 LOAD_PROC (WSACloseEvent
);
7233 LOAD_PROC (connect
);
7234 LOAD_PROC (ioctlsocket
);
7237 LOAD_PROC (closesocket
);
7238 LOAD_PROC (shutdown
);
7241 LOAD_PROC (inet_addr
);
7242 LOAD_PROC (gethostname
);
7243 LOAD_PROC (gethostbyname
);
7244 LOAD_PROC (getservbyname
);
7245 LOAD_PROC (getpeername
);
7246 LOAD_PROC (WSACleanup
);
7247 LOAD_PROC (setsockopt
);
7249 LOAD_PROC (getsockname
);
7251 LOAD_PROC (recvfrom
);
7255 /* specify version 1.1 of winsock */
7256 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7258 if (winsockData
.wVersion
!= 0x101)
7263 /* Report that winsock exists and is usable, but leave
7264 socket functions disabled. I am assuming that calling
7265 WSAStartup does not require any network interaction,
7266 and in particular does not cause or require a dial-up
7267 connection to be established. */
7270 FreeLibrary (winsock_lib
);
7278 FreeLibrary (winsock_lib
);
7288 /* Function to map winsock error codes to errno codes for those errno
7289 code defined in errno.h (errno values not defined by errno.h are
7290 already in nt/inc/sys/socket.h). */
7297 if (winsock_lib
== NULL
)
7300 wsa_err
= pfn_WSAGetLastError ();
7304 case WSAEACCES
: errno
= EACCES
; break;
7305 case WSAEBADF
: errno
= EBADF
; break;
7306 case WSAEFAULT
: errno
= EFAULT
; break;
7307 case WSAEINTR
: errno
= EINTR
; break;
7308 case WSAEINVAL
: errno
= EINVAL
; break;
7309 case WSAEMFILE
: errno
= EMFILE
; break;
7310 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7311 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7312 case WSAEWOULDBLOCK
: errno
= EWOULDBLOCK
; break;
7313 case WSAENOTCONN
: errno
= ENOTCONN
; break;
7314 default: errno
= wsa_err
; break;
7322 if (winsock_lib
!= NULL
)
7323 pfn_WSASetLastError (0);
7326 /* Extend strerror to handle the winsock-specific error codes. */
7330 } _wsa_errlist
[] = {
7331 {WSAEINTR
, "Interrupted function call"},
7332 {WSAEBADF
, "Bad file descriptor"},
7333 {WSAEACCES
, "Permission denied"},
7334 {WSAEFAULT
, "Bad address"},
7335 {WSAEINVAL
, "Invalid argument"},
7336 {WSAEMFILE
, "Too many open files"},
7338 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7339 {WSAEINPROGRESS
, "Operation now in progress"},
7340 {WSAEALREADY
, "Operation already in progress"},
7341 {WSAENOTSOCK
, "Socket operation on non-socket"},
7342 {WSAEDESTADDRREQ
, "Destination address required"},
7343 {WSAEMSGSIZE
, "Message too long"},
7344 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7345 {WSAENOPROTOOPT
, "Bad protocol option"},
7346 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7347 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7348 {WSAEOPNOTSUPP
, "Operation not supported"},
7349 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7350 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7351 {WSAEADDRINUSE
, "Address already in use"},
7352 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7353 {WSAENETDOWN
, "Network is down"},
7354 {WSAENETUNREACH
, "Network is unreachable"},
7355 {WSAENETRESET
, "Network dropped connection on reset"},
7356 {WSAECONNABORTED
, "Software caused connection abort"},
7357 {WSAECONNRESET
, "Connection reset by peer"},
7358 {WSAENOBUFS
, "No buffer space available"},
7359 {WSAEISCONN
, "Socket is already connected"},
7360 {WSAENOTCONN
, "Socket is not connected"},
7361 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7362 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7363 {WSAETIMEDOUT
, "Connection timed out"},
7364 {WSAECONNREFUSED
, "Connection refused"},
7365 {WSAELOOP
, "Network loop"}, /* not sure */
7366 {WSAENAMETOOLONG
, "Name is too long"},
7367 {WSAEHOSTDOWN
, "Host is down"},
7368 {WSAEHOSTUNREACH
, "No route to host"},
7369 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7370 {WSAEPROCLIM
, "Too many processes"},
7371 {WSAEUSERS
, "Too many users"}, /* not sure */
7372 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7373 {WSAESTALE
, "Data is stale"}, /* not sure */
7374 {WSAEREMOTE
, "Remote error"}, /* not sure */
7376 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7377 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7378 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7379 {WSAEDISCON
, "Graceful shutdown in progress"},
7381 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7382 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7383 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7384 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7385 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7386 {WSASYSCALLFAILURE
, "System call failure"},
7387 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7388 {WSATYPE_NOT_FOUND
, "Class type not found"},
7389 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7390 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7391 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7394 {WSAHOST_NOT_FOUND
, "Host not found"},
7395 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7396 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7397 {WSANO_DATA
, "Valid name, no data record of requested type"},
7403 sys_strerror (int error_no
)
7406 static char unknown_msg
[40];
7408 if (error_no
>= 0 && error_no
< sys_nerr
)
7409 return sys_errlist
[error_no
];
7411 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7412 if (_wsa_errlist
[i
].errnum
== error_no
)
7413 return _wsa_errlist
[i
].msg
;
7415 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7419 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7420 but I believe the method of keeping the socket handle separate (and
7421 insuring it is not inheritable) is the correct one. */
7423 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7425 static int socket_to_fd (SOCKET s
);
7428 sys_socket (int af
, int type
, int protocol
)
7432 if (winsock_lib
== NULL
)
7440 /* call the real socket function */
7441 s
= pfn_socket (af
, type
, protocol
);
7443 if (s
!= INVALID_SOCKET
)
7444 return socket_to_fd (s
);
7450 /* Convert a SOCKET to a file descriptor. */
7452 socket_to_fd (SOCKET s
)
7457 /* Although under NT 3.5 _open_osfhandle will accept a socket
7458 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7459 that does not work under NT 3.1. However, we can get the same
7460 effect by using a backdoor function to replace an existing
7461 descriptor handle with the one we want. */
7463 /* allocate a file descriptor (with appropriate flags) */
7464 fd
= _open ("NUL:", _O_RDWR
);
7467 /* Make a non-inheritable copy of the socket handle. Note
7468 that it is possible that sockets aren't actually kernel
7469 handles, which appears to be the case on Windows 9x when
7470 the MS Proxy winsock client is installed. */
7472 /* Apparently there is a bug in NT 3.51 with some service
7473 packs, which prevents using DuplicateHandle to make a
7474 socket handle non-inheritable (causes WSACleanup to
7475 hang). The work-around is to use SetHandleInformation
7476 instead if it is available and implemented. */
7477 if (pfn_SetHandleInformation
)
7479 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7483 HANDLE parent
= GetCurrentProcess ();
7484 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7486 if (DuplicateHandle (parent
,
7492 DUPLICATE_SAME_ACCESS
))
7494 /* It is possible that DuplicateHandle succeeds even
7495 though the socket wasn't really a kernel handle,
7496 because a real handle has the same value. So
7497 test whether the new handle really is a socket. */
7498 long nonblocking
= 0;
7499 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7501 pfn_closesocket (s
);
7506 CloseHandle (new_s
);
7511 eassert (fd
< MAXDESC
);
7512 fd_info
[fd
].hnd
= (HANDLE
) s
;
7514 /* set our own internal flags */
7515 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7521 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7523 /* attach child_process to fd_info */
7524 if (fd_info
[ fd
].cp
!= NULL
)
7526 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7530 fd_info
[ fd
].cp
= cp
;
7533 winsock_inuse
++; /* count open sockets */
7541 pfn_closesocket (s
);
7547 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7549 if (winsock_lib
== NULL
)
7552 return SOCKET_ERROR
;
7556 if (fd_info
[s
].flags
& FILE_SOCKET
)
7558 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7559 if (rc
== SOCKET_ERROR
)
7564 return SOCKET_ERROR
;
7568 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7570 if (winsock_lib
== NULL
)
7573 return SOCKET_ERROR
;
7577 if (fd_info
[s
].flags
& FILE_SOCKET
)
7579 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7580 if (rc
== SOCKET_ERROR
)
7583 /* If this is a non-blocking 'connect', set the bit in flags
7584 that will tell reader_thread to wait for connection
7585 before trying to read. */
7586 if (errno
== EWOULDBLOCK
&& (fd_info
[s
].flags
& FILE_NDELAY
) != 0)
7588 errno
= EINPROGRESS
; /* that's what process.c expects */
7589 fd_info
[s
].flags
|= FILE_CONNECT
;
7595 return SOCKET_ERROR
;
7599 sys_htons (u_short hostshort
)
7601 return (winsock_lib
!= NULL
) ?
7602 pfn_htons (hostshort
) : hostshort
;
7606 sys_ntohs (u_short netshort
)
7608 return (winsock_lib
!= NULL
) ?
7609 pfn_ntohs (netshort
) : netshort
;
7613 sys_inet_addr (const char * cp
)
7615 return (winsock_lib
!= NULL
) ?
7616 pfn_inet_addr (cp
) : INADDR_NONE
;
7620 sys_gethostname (char * name
, int namelen
)
7622 if (winsock_lib
!= NULL
)
7627 retval
= pfn_gethostname (name
, namelen
);
7628 if (retval
== SOCKET_ERROR
)
7633 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7634 return !GetComputerName (name
, (DWORD
*)&namelen
);
7637 return SOCKET_ERROR
;
7641 sys_gethostbyname (const char * name
)
7643 struct hostent
* host
;
7644 int h_err
= h_errno
;
7646 if (winsock_lib
== NULL
)
7648 h_errno
= NO_RECOVERY
;
7654 host
= pfn_gethostbyname (name
);
7666 sys_getservbyname (const char * name
, const char * proto
)
7668 struct servent
* serv
;
7670 if (winsock_lib
== NULL
)
7677 serv
= pfn_getservbyname (name
, proto
);
7684 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7686 if (winsock_lib
== NULL
)
7689 return SOCKET_ERROR
;
7693 if (fd_info
[s
].flags
& FILE_SOCKET
)
7695 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7696 if (rc
== SOCKET_ERROR
)
7701 return SOCKET_ERROR
;
7705 sys_shutdown (int s
, int how
)
7707 if (winsock_lib
== NULL
)
7710 return SOCKET_ERROR
;
7714 if (fd_info
[s
].flags
& FILE_SOCKET
)
7716 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7717 if (rc
== SOCKET_ERROR
)
7722 return SOCKET_ERROR
;
7726 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7728 if (winsock_lib
== NULL
)
7731 return SOCKET_ERROR
;
7735 if (fd_info
[s
].flags
& FILE_SOCKET
)
7737 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7738 (const char *)optval
, optlen
);
7739 if (rc
== SOCKET_ERROR
)
7744 return SOCKET_ERROR
;
7748 sys_listen (int s
, int backlog
)
7750 if (winsock_lib
== NULL
)
7753 return SOCKET_ERROR
;
7757 if (fd_info
[s
].flags
& FILE_SOCKET
)
7759 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7760 if (rc
== SOCKET_ERROR
)
7763 fd_info
[s
].flags
|= FILE_LISTEN
;
7767 return SOCKET_ERROR
;
7771 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7773 if (winsock_lib
== NULL
)
7776 return SOCKET_ERROR
;
7780 if (fd_info
[s
].flags
& FILE_SOCKET
)
7782 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7783 if (rc
== SOCKET_ERROR
)
7788 return SOCKET_ERROR
;
7792 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7794 if (winsock_lib
== NULL
)
7801 if (fd_info
[s
].flags
& FILE_LISTEN
)
7803 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7805 if (t
== INVALID_SOCKET
)
7808 fd
= socket_to_fd (t
);
7812 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7813 ResetEvent (fd_info
[s
].cp
->char_avail
);
7822 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7823 struct sockaddr
* from
, int * fromlen
)
7825 if (winsock_lib
== NULL
)
7828 return SOCKET_ERROR
;
7832 if (fd_info
[s
].flags
& FILE_SOCKET
)
7834 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7835 if (rc
== SOCKET_ERROR
)
7840 return SOCKET_ERROR
;
7844 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7845 const struct sockaddr
* to
, int tolen
)
7847 if (winsock_lib
== NULL
)
7850 return SOCKET_ERROR
;
7854 if (fd_info
[s
].flags
& FILE_SOCKET
)
7856 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7857 if (rc
== SOCKET_ERROR
)
7862 return SOCKET_ERROR
;
7865 /* Windows does not have an fcntl function. Provide an implementation
7866 good enough for Emacs. */
7868 fcntl (int s
, int cmd
, int options
)
7870 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7871 invoked in a context where fd1 is closed and all descriptors less
7872 than fd1 are open, so sys_dup is an adequate implementation. */
7873 if (cmd
== F_DUPFD_CLOEXEC
)
7877 if (fd_info
[s
].flags
& FILE_SOCKET
)
7879 if (winsock_lib
== NULL
)
7885 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7887 unsigned long nblock
= 1;
7888 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7889 if (rc
== SOCKET_ERROR
)
7891 /* Keep track of the fact that we set this to non-blocking. */
7892 fd_info
[s
].flags
|= FILE_NDELAY
;
7898 return SOCKET_ERROR
;
7901 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
7902 == (FILE_PIPE
| FILE_WRITE
))
7904 /* Force our writes to pipes be non-blocking. */
7905 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7907 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
7908 DWORD pipe_mode
= PIPE_NOWAIT
;
7910 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
7912 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
7913 return SOCKET_ERROR
;
7915 fd_info
[s
].flags
|= FILE_NDELAY
;
7921 return SOCKET_ERROR
;
7925 return SOCKET_ERROR
;
7929 /* Shadow main io functions: we need to handle pipes and sockets more
7943 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7945 child_process
* cp
= fd_info
[fd
].cp
;
7947 fd_info
[fd
].cp
= NULL
;
7949 if (CHILD_ACTIVE (cp
))
7951 /* if last descriptor to active child_process then cleanup */
7953 for (i
= 0; i
< MAXDESC
; i
++)
7957 if (fd_info
[i
].cp
== cp
)
7962 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7964 if (winsock_lib
== NULL
) emacs_abort ();
7966 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7967 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7969 winsock_inuse
--; /* count open sockets */
7971 /* If the process handle is NULL, it's either a socket
7972 or serial connection, or a subprocess that was
7973 already reaped by reap_subprocess, but whose
7974 resources were not yet freed, because its output was
7975 not fully read yet by the time it was reaped. (This
7976 usually happens with async subprocesses whose output
7977 is being read by Emacs.) Otherwise, this process was
7978 not reaped yet, so we set its FD to a negative value
7979 to make sure sys_select will eventually get to
7980 calling the SIGCHLD handler for it, which will then
7981 invoke waitpid and reap_subprocess. */
7982 if (cp
->procinfo
.hProcess
== NULL
)
7990 if (fd
>= 0 && fd
< MAXDESC
)
7991 fd_info
[fd
].flags
= 0;
7993 /* Note that sockets do not need special treatment here (at least on
7994 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7995 closesocket is equivalent to CloseHandle, which is to be expected
7996 because socket handles are fully fledged kernel handles. */
8008 if (new_fd
>= 0 && new_fd
< MAXDESC
)
8010 /* duplicate our internal info as well */
8011 fd_info
[new_fd
] = fd_info
[fd
];
8017 sys_dup2 (int src
, int dst
)
8021 if (dst
< 0 || dst
>= MAXDESC
)
8027 /* make sure we close the destination first if it's a pipe or socket */
8028 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
8031 rc
= _dup2 (src
, dst
);
8034 /* duplicate our internal info as well */
8035 fd_info
[dst
] = fd_info
[src
];
8041 pipe2 (int * phandles
, int pipe2_flags
)
8046 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
8048 /* make pipe handles non-inheritable; when we spawn a child, we
8049 replace the relevant handle with an inheritable one. Also put
8050 pipes into binary mode; we will do text mode translation ourselves
8052 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
8056 /* Protect against overflow, since Windows can open more handles than
8057 our fd_info array has room for. */
8058 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
8060 _close (phandles
[0]);
8061 _close (phandles
[1]);
8067 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
8068 fd_info
[phandles
[0]].flags
= flags
;
8070 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
8071 fd_info
[phandles
[1]].flags
= flags
;
8078 /* Function to do blocking read of one byte, needed to implement
8079 select. It is only allowed on communication ports, sockets, or
8082 _sys_read_ahead (int fd
)
8087 if (fd
< 0 || fd
>= MAXDESC
)
8088 return STATUS_READ_ERROR
;
8090 cp
= fd_info
[fd
].cp
;
8092 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8093 return STATUS_READ_ERROR
;
8095 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
8096 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
8098 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
8102 if ((fd_info
[fd
].flags
& FILE_CONNECT
) != 0)
8103 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd
));
8104 cp
->status
= STATUS_READ_IN_PROGRESS
;
8106 if (fd_info
[fd
].flags
& FILE_PIPE
)
8108 rc
= _read (fd
, &cp
->chr
, sizeof (char));
8110 /* Give subprocess time to buffer some more output for us before
8111 reporting that input is available; we need this because Windows 95
8112 connects DOS programs to pipes by making the pipe appear to be
8113 the normal console stdout - as a result most DOS programs will
8114 write to stdout without buffering, ie. one character at a
8115 time. Even some W32 programs do this - "dir" in a command
8116 shell on NT is very slow if we don't do this. */
8119 int wait
= w32_pipe_read_delay
;
8125 /* Yield remainder of our time slice, effectively giving a
8126 temporary priority boost to the child process. */
8130 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8132 HANDLE hnd
= fd_info
[fd
].hnd
;
8133 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8136 /* Configure timeouts for blocking read. */
8137 if (!GetCommTimeouts (hnd
, &ct
))
8139 cp
->status
= STATUS_READ_ERROR
;
8140 return STATUS_READ_ERROR
;
8142 ct
.ReadIntervalTimeout
= 0;
8143 ct
.ReadTotalTimeoutMultiplier
= 0;
8144 ct
.ReadTotalTimeoutConstant
= 0;
8145 if (!SetCommTimeouts (hnd
, &ct
))
8147 cp
->status
= STATUS_READ_ERROR
;
8148 return STATUS_READ_ERROR
;
8151 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8153 if (GetLastError () != ERROR_IO_PENDING
)
8155 cp
->status
= STATUS_READ_ERROR
;
8156 return STATUS_READ_ERROR
;
8158 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8160 cp
->status
= STATUS_READ_ERROR
;
8161 return STATUS_READ_ERROR
;
8165 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8167 unsigned long nblock
= 0;
8168 /* We always want this to block, so temporarily disable NDELAY. */
8169 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8170 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8172 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8174 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8177 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8181 if (rc
== sizeof (char))
8182 cp
->status
= STATUS_READ_SUCCEEDED
;
8184 cp
->status
= STATUS_READ_FAILED
;
8190 _sys_wait_accept (int fd
)
8196 if (fd
< 0 || fd
>= MAXDESC
)
8197 return STATUS_READ_ERROR
;
8199 cp
= fd_info
[fd
].cp
;
8201 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8202 return STATUS_READ_ERROR
;
8204 cp
->status
= STATUS_READ_FAILED
;
8206 hEv
= pfn_WSACreateEvent ();
8207 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8208 if (rc
!= SOCKET_ERROR
)
8211 rc
= WaitForSingleObject (hEv
, 500);
8213 } while (rc
== WAIT_TIMEOUT
8214 && cp
->status
!= STATUS_READ_ERROR
8216 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8217 if (rc
== WAIT_OBJECT_0
)
8218 cp
->status
= STATUS_READ_SUCCEEDED
;
8220 pfn_WSACloseEvent (hEv
);
8226 _sys_wait_connect (int fd
)
8232 if (fd
< 0 || fd
>= MAXDESC
)
8233 return STATUS_READ_ERROR
;
8235 cp
= fd_info
[fd
].cp
;
8236 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8237 return STATUS_READ_ERROR
;
8239 cp
->status
= STATUS_READ_FAILED
;
8241 hEv
= pfn_WSACreateEvent ();
8242 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_CONNECT
);
8243 if (rc
!= SOCKET_ERROR
)
8246 rc
= WaitForSingleObject (hEv
, 500);
8248 } while (rc
== WAIT_TIMEOUT
8249 && cp
->status
!= STATUS_READ_ERROR
8251 if (rc
== WAIT_OBJECT_0
)
8253 /* We've got an event, but it could be a successful
8254 connection, or it could be a failure. Find out
8256 WSANETWORKEVENTS events
;
8258 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd
), hEv
, &events
);
8259 if ((events
.lNetworkEvents
& FD_CONNECT
) != 0
8260 && events
.iErrorCode
[FD_CONNECT_BIT
])
8262 cp
->status
= STATUS_CONNECT_FAILED
;
8263 cp
->errcode
= events
.iErrorCode
[FD_CONNECT_BIT
];
8267 cp
->status
= STATUS_READ_SUCCEEDED
;
8271 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8274 pfn_WSACloseEvent (hEv
);
8280 sys_read (int fd
, char * buffer
, unsigned int count
)
8285 char * orig_buffer
= buffer
;
8293 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8295 child_process
*cp
= fd_info
[fd
].cp
;
8297 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8305 /* re-read CR carried over from last read */
8306 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8308 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8312 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8315 /* presence of a child_process structure means we are operating in
8316 non-blocking mode - otherwise we just call _read directly.
8317 Note that the child_process structure might be missing because
8318 reap_subprocess has been called; in this case the pipe is
8319 already broken, so calling _read on it is okay. */
8322 int current_status
= cp
->status
;
8324 switch (current_status
)
8326 case STATUS_READ_FAILED
:
8327 case STATUS_READ_ERROR
:
8328 /* report normal EOF if nothing in buffer */
8330 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8333 case STATUS_READ_READY
:
8334 case STATUS_READ_IN_PROGRESS
:
8335 DebPrint (("sys_read called when read is in progress\n"));
8336 errno
= EWOULDBLOCK
;
8339 case STATUS_READ_SUCCEEDED
:
8340 /* consume read-ahead char */
8341 *buffer
++ = cp
->chr
;
8344 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8345 ResetEvent (cp
->char_avail
);
8347 case STATUS_READ_ACKNOWLEDGED
:
8348 case STATUS_CONNECT_FAILED
:
8352 DebPrint (("sys_read: bad status %d\n", current_status
));
8357 if (fd_info
[fd
].flags
& FILE_PIPE
)
8359 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8360 to_read
= min (waiting
, (DWORD
) count
);
8363 nchars
+= _read (fd
, buffer
, to_read
);
8365 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8367 HANDLE hnd
= fd_info
[fd
].hnd
;
8368 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8374 /* Configure timeouts for non-blocking read. */
8375 if (!GetCommTimeouts (hnd
, &ct
))
8380 ct
.ReadIntervalTimeout
= MAXDWORD
;
8381 ct
.ReadTotalTimeoutMultiplier
= 0;
8382 ct
.ReadTotalTimeoutConstant
= 0;
8383 if (!SetCommTimeouts (hnd
, &ct
))
8389 if (!ResetEvent (ovl
->hEvent
))
8394 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8396 if (GetLastError () != ERROR_IO_PENDING
)
8401 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8410 else /* FILE_SOCKET */
8412 if (winsock_lib
== NULL
) emacs_abort ();
8414 /* When a non-blocking 'connect' call fails,
8415 wait_reading_process_output detects this by calling
8416 'getpeername', and then attempts to obtain the connection
8417 error code by trying to read 1 byte from the socket. If
8418 we try to serve that read by calling 'recv' below, the
8419 error we get is a generic WSAENOTCONN, not the actual
8420 connection error. So instead, we use the actual error
8421 code stashed by '_sys_wait_connect' in cp->errcode.
8422 Alternatively, we could have used 'getsockopt', like on
8423 GNU/Linux, but: (a) I have no idea whether the winsock
8424 version could hang, as it does "on some systems" (see the
8425 comment in process.c); and (b) 'getsockopt' on Windows is
8426 documented to clear the socket error for the entire
8427 process, which I'm not sure is TRT; FIXME. */
8428 if (current_status
== STATUS_CONNECT_FAILED
8429 && (fd_info
[fd
].flags
& FILE_CONNECT
) != 0
8430 && cp
->errcode
!= 0)
8432 pfn_WSASetLastError (cp
->errcode
);
8436 /* Do the equivalent of a non-blocking read. */
8437 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8438 if (waiting
== 0 && nchars
== 0)
8440 errno
= EWOULDBLOCK
;
8446 /* always use binary mode for sockets */
8447 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8448 if (res
== SOCKET_ERROR
)
8451 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8452 errno
, SOCK_HANDLE (fd
)));
8461 int nread
= _read (fd
, buffer
, count
);
8464 else if (nchars
== 0)
8469 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8470 /* Perform text mode translation if required. */
8471 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8473 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8474 /* If buffer contains only CR, return that. To be absolutely
8475 sure we should attempt to read the next char, but in
8476 practice a CR to be followed by LF would not appear by
8477 itself in the buffer. */
8478 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8480 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8486 nchars
= _read (fd
, buffer
, count
);
8491 /* From w32xfns.c */
8492 extern HANDLE interrupt_handle
;
8495 sys_write (int fd
, const void * buffer
, unsigned int count
)
8506 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8508 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8514 /* Perform text mode translation if required. */
8515 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8518 const unsigned char * src
= buffer
;
8519 unsigned char * dst
;
8522 SAFE_NALLOCA (tmpbuf
, 2, count
);
8527 unsigned char *next
;
8528 /* Copy next line or remaining bytes. */
8529 next
= _memccpy (dst
, src
, '\n', nbytes
);
8532 /* Copied one line ending with '\n'. */
8533 int copied
= next
- dst
;
8536 /* Insert '\r' before '\n'. */
8543 /* Copied remaining partial line -> now finished. */
8550 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8552 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8553 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8554 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8557 /* This is async (a.k.a. "overlapped") I/O, so the return value
8558 of FALSE from WriteFile means either an error or the output
8559 will be completed asynchronously (ERROR_IO_PENDING). */
8560 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8562 if (GetLastError () != ERROR_IO_PENDING
)
8569 /* Wait for the write to complete, and watch C-g while
8571 if (detect_input_pending ())
8572 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8573 INFINITE
, QS_ALLINPUT
);
8575 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8579 /* User pressed C-g, cancel write, then leave.
8580 Don't bother cleaning up as we may only get stuck
8581 in buggy drivers. */
8582 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8584 errno
= EIO
; /* Why not EINTR? */
8587 case WAIT_OBJECT_0
+ 1:
8588 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8598 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8600 unsigned long nblock
= 0;
8601 if (winsock_lib
== NULL
) emacs_abort ();
8603 /* TODO: implement select() properly so non-blocking I/O works. */
8604 /* For now, make sure the write blocks. */
8605 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8606 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8608 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8610 /* Set the socket back to non-blocking if it was before,
8611 for other operations that support it. */
8612 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8615 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8618 if (nchars
== SOCKET_ERROR
)
8620 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8621 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8627 /* Some networked filesystems don't like too large writes, so
8628 break them into smaller chunks. See the Comments section of
8629 the MSDN documentation of WriteFile for details behind the
8630 choice of the value of CHUNK below. See also the thread
8631 http://thread.gmane.org/gmane.comp.version-control.git/145294
8632 in the git mailing list. */
8633 const unsigned char *p
= buffer
;
8634 const unsigned chunk
= 30 * 1024 * 1024;
8639 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8640 int n
= _write (fd
, p
, this_chunk
);
8645 /* When there's no buffer space in a pipe that is in the
8646 non-blocking mode, _write returns ENOSPC. We return
8647 EAGAIN instead, which should trigger the logic in
8648 send_process that enters waiting loop and calls
8649 wait_reading_process_output to allow process input to
8650 be accepted during the wait. Those calls to
8651 wait_reading_process_output allow sys_select to
8652 notice when process input becomes available, thus
8653 avoiding deadlock whereby each side of the pipe is
8654 blocked on write, waiting for the other party to read
8655 its end of the pipe. */
8658 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8659 == (FILE_PIPE
| FILE_NDELAY
)))
8664 else if (n
< this_chunk
)
8676 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8678 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8680 /* Return information about network interface IFNAME, or about all
8681 interfaces (if IFNAME is nil). */
8683 network_interface_get_info (Lisp_Object ifname
)
8685 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8686 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8687 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8688 Lisp_Object res
= Qnil
;
8690 if (retval
== ERROR_BUFFER_OVERFLOW
)
8692 ainfo
= xrealloc (ainfo
, ainfo_len
);
8693 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8696 if (retval
== ERROR_SUCCESS
)
8698 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8699 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8701 struct sockaddr_in sa
;
8703 /* For the below, we need some winsock functions, so make sure
8704 the winsock DLL is loaded. If we cannot successfully load
8705 it, they will have no use of the information we provide,
8707 if (!winsock_lib
&& !init_winsock (1))
8710 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8712 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8714 /* Present Unix-compatible interface names, instead of the
8715 Windows names, which are really GUIDs not readable by
8717 static const char *ifmt
[] = {
8718 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8733 switch (adapter
->Type
)
8735 case MIB_IF_TYPE_ETHERNET
:
8736 /* Windows before Vista reports wireless adapters as
8737 Ethernet. Work around by looking at the Description
8739 if (strstr (adapter
->Description
, "Wireless "))
8742 if_num
= wlan_count
++;
8746 ifmt_idx
= ETHERNET
;
8747 if_num
= eth_count
++;
8750 case MIB_IF_TYPE_TOKENRING
:
8751 ifmt_idx
= TOKENRING
;
8752 if_num
= tr_count
++;
8754 case MIB_IF_TYPE_FDDI
:
8756 if_num
= fddi_count
++;
8758 case MIB_IF_TYPE_PPP
:
8760 if_num
= ppp_count
++;
8762 case MIB_IF_TYPE_SLIP
:
8764 if_num
= sl_count
++;
8766 case IF_TYPE_IEEE80211
:
8768 if_num
= wlan_count
++;
8770 case MIB_IF_TYPE_LOOPBACK
:
8773 ifmt_idx
= LOOPBACK
;
8774 if_num
= lo_count
++;
8780 ifmt_idx
= OTHER_IF
;
8781 if_num
= ifx_count
++;
8784 if (ifmt_idx
== NONE
)
8786 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8788 sa
.sin_family
= AF_INET
;
8789 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8790 if (ip_addr
== INADDR_NONE
)
8792 /* Bogus address, skip this interface. */
8795 sa
.sin_addr
.s_addr
= ip_addr
;
8798 res
= Fcons (Fcons (build_string (namebuf
),
8799 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8800 sizeof (struct sockaddr
))),
8802 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8804 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8805 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8806 Lisp_Object flags
= Qnil
;
8810 /* Flags. We guess most of them by type, since the
8811 Windows flags are different and hard to get by. */
8812 flags
= Fcons (intern ("up"), flags
);
8813 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8815 flags
= Fcons (intern ("broadcast"), flags
);
8816 flags
= Fcons (intern ("multicast"), flags
);
8818 flags
= Fcons (intern ("running"), flags
);
8819 if (ifmt_idx
== PPP
)
8821 flags
= Fcons (intern ("pointopoint"), flags
);
8822 flags
= Fcons (intern ("noarp"), flags
);
8824 if (adapter
->HaveWins
)
8825 flags
= Fcons (intern ("WINS"), flags
);
8826 if (adapter
->DhcpEnabled
)
8827 flags
= Fcons (intern ("dynamic"), flags
);
8829 res
= Fcons (flags
, res
);
8831 /* Hardware address and its family. */
8832 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8833 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8834 /* Windows does not support AF_LINK or AF_PACKET family
8835 of addresses. Use an arbitrary family number that is
8836 identical to what GNU/Linux returns. */
8837 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8840 sa
.sin_family
= AF_INET
;
8841 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8842 if (net_mask
!= INADDR_NONE
)
8844 sa
.sin_addr
.s_addr
= net_mask
;
8846 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8847 sizeof (struct sockaddr
)),
8851 res
= Fcons (Qnil
, res
);
8853 sa
.sin_family
= AF_INET
;
8854 if (ip_addr
!= INADDR_NONE
)
8856 /* Broadcast address is only reported by
8857 GetAdaptersAddresses, which is of limited
8858 availability. Generate it on our own. */
8859 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8861 sa
.sin_addr
.s_addr
= bcast_addr
;
8863 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8864 sizeof (struct sockaddr
)),
8868 sa
.sin_addr
.s_addr
= ip_addr
;
8870 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8871 sizeof (struct sockaddr
)),
8875 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8878 /* GetAdaptersInfo is documented to not report loopback
8879 interfaces, so we generate one out of thin air. */
8882 sa
.sin_family
= AF_INET
;
8886 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8887 res
= Fcons (Fcons (build_string ("lo"),
8888 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8889 sizeof (struct sockaddr
))),
8892 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8894 res
= Fcons (Fcons (intern ("running"),
8895 Fcons (intern ("loopback"),
8896 Fcons (intern ("up"), Qnil
))), Qnil
);
8897 /* 772 is what 3 different GNU/Linux systems report for
8898 the loopback interface. */
8899 res
= Fcons (Fcons (make_number (772),
8900 Fmake_vector (make_number (6),
8903 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8904 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8905 sizeof (struct sockaddr
)),
8907 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8908 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8909 sizeof (struct sockaddr
)),
8911 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8912 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8913 sizeof (struct sockaddr
)),
8926 network_interface_list (void)
8928 return network_interface_get_info (Qnil
);
8932 network_interface_info (Lisp_Object ifname
)
8934 CHECK_STRING (ifname
);
8935 return network_interface_get_info (ifname
);
8939 /* The Windows CRT functions are "optimized for speed", so they don't
8940 check for timezone and DST changes if they were last called less
8941 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8942 all Emacs features that repeatedly call time functions (e.g.,
8943 display-time) are in real danger of missing timezone and DST
8944 changes. Calling tzset before each localtime call fixes that. */
8946 sys_localtime (const time_t *t
)
8949 return localtime (t
);
8954 /* Try loading LIBRARY_ID from the file(s) specified in
8955 Vdynamic_library_alist. If the library is loaded successfully,
8956 return the handle of the DLL, and record the filename in the
8957 property :loaded-from of LIBRARY_ID. If the library could not be
8958 found, or when it was already loaded (because the handle is not
8959 recorded anywhere, and so is lost after use), return NULL.
8961 We could also save the handle in :loaded-from, but currently
8962 there's no use case for it. */
8964 w32_delayed_load (Lisp_Object library_id
)
8966 HMODULE dll_handle
= NULL
;
8968 CHECK_SYMBOL (library_id
);
8970 if (CONSP (Vdynamic_library_alist
)
8971 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8973 Lisp_Object found
= Qnil
;
8974 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8977 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8979 Lisp_Object dll
= XCAR (dlls
);
8980 char name
[MAX_UTF8_PATH
];
8984 dll
= ENCODE_FILE (dll
);
8985 if (w32_unicode_filenames
)
8987 wchar_t name_w
[MAX_PATH
];
8989 filename_to_utf16 (SSDATA (dll
), name_w
);
8990 dll_handle
= LoadLibraryW (name_w
);
8993 res
= GetModuleFileNameW (dll_handle
, name_w
,
8996 filename_from_utf16 (name_w
, name
);
9001 char name_a
[MAX_PATH
];
9003 filename_to_ansi (SSDATA (dll
), name_a
);
9004 dll_handle
= LoadLibraryA (name_a
);
9007 res
= GetModuleFileNameA (dll_handle
, name_a
,
9010 filename_from_ansi (name_a
, name
);
9015 ptrdiff_t len
= strlen (name
);
9018 /* Possibly truncated */
9019 ? make_specified_string (name
, -1, len
, 1)
9021 /* This prevents thread start and end notifications
9022 from being sent to the DLL, for every thread we
9023 start. We don't need those notifications because
9024 threads we create never use any of these DLLs, only
9025 the main thread uses them. This is supposed to
9026 speed up thread creation. */
9027 DisableThreadLibraryCalls (dll_handle
);
9032 Fput (library_id
, QCloaded_from
, found
);
9040 check_windows_init_file (void)
9042 /* A common indication that Emacs is not installed properly is when
9043 it cannot find the Windows installation file. If this file does
9044 not exist in the expected place, tell the user. */
9046 if (!noninteractive
&& !inhibit_window_system
9047 /* Vload_path is not yet initialized when we are loading
9049 && NILP (Vpurify_flag
))
9051 Lisp_Object init_file
;
9054 /* Implementation note: this function runs early during Emacs
9055 startup, before startup.el is run. So Vload_path is still in
9056 its initial unibyte form, but it holds UTF-8 encoded file
9057 names, since init_callproc was already called. So we do not
9058 need to ENCODE_FILE here, but we do need to convert the file
9059 names from UTF-8 to ANSI. */
9060 init_file
= build_string ("term/w32-win");
9061 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
9064 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
9065 char *init_file_name
= SDATA (init_file
);
9066 char *load_path
= SDATA (load_path_print
);
9067 char *buffer
= alloca (1024
9068 + strlen (init_file_name
)
9069 + strlen (load_path
));
9074 "The Emacs Windows initialization file \"%s.el\" "
9075 "could not be found in your Emacs installation. "
9076 "Emacs checked the following directories for this file:\n"
9078 "When Emacs cannot find this file, it usually means that it "
9079 "was not installed properly, or its distribution file was "
9080 "not unpacked properly.\nSee the README.W32 file in the "
9081 "top-level Emacs directory for more information.",
9082 init_file_name
, load_path
);
9083 needed
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
9087 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
9089 pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
9091 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
9092 NULL
, 0, NULL
, NULL
);
9095 char *msg_a
= alloca (needed
+ 1);
9097 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
9104 "Emacs Abort Dialog",
9105 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
9106 /* Use the low-level system abort. */
9117 term_ntproc (int ignored
)
9123 /* shutdown the socket interface if necessary */
9130 init_ntproc (int dumping
)
9132 sigset_t initial_mask
= 0;
9134 /* Initialize the socket interface now if available and requested by
9135 the user by defining PRELOAD_WINSOCK; otherwise loading will be
9136 delayed until open-network-stream is called (w32-has-winsock can
9137 also be used to dynamically load or reload winsock).
9139 Conveniently, init_environment is called before us, so
9140 PRELOAD_WINSOCK can be set in the registry. */
9142 /* Always initialize this correctly. */
9145 if (getenv ("PRELOAD_WINSOCK") != NULL
)
9146 init_winsock (TRUE
);
9148 /* Initial preparation for subprocess support: replace our standard
9149 handles with non-inheritable versions. */
9152 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
9153 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
9154 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
9156 parent
= GetCurrentProcess ();
9158 /* ignore errors when duplicating and closing; typically the
9159 handles will be invalid when running as a gui program. */
9160 DuplicateHandle (parent
,
9161 GetStdHandle (STD_INPUT_HANDLE
),
9166 DUPLICATE_SAME_ACCESS
);
9168 DuplicateHandle (parent
,
9169 GetStdHandle (STD_OUTPUT_HANDLE
),
9174 DUPLICATE_SAME_ACCESS
);
9176 DuplicateHandle (parent
,
9177 GetStdHandle (STD_ERROR_HANDLE
),
9182 DUPLICATE_SAME_ACCESS
);
9188 if (stdin_save
!= INVALID_HANDLE_VALUE
)
9189 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
9191 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
9194 if (stdout_save
!= INVALID_HANDLE_VALUE
)
9195 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
9197 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9200 if (stderr_save
!= INVALID_HANDLE_VALUE
)
9201 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
9203 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
9207 /* unfortunately, atexit depends on implementation of malloc */
9208 /* atexit (term_ntproc); */
9211 /* Make sure we start with all signals unblocked. */
9212 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
9213 signal (SIGABRT
, term_ntproc
);
9217 /* determine which drives are fixed, for GetCachedVolumeInformation */
9219 /* GetDriveType must have trailing backslash. */
9220 char drive
[] = "A:\\";
9222 /* Loop over all possible drive letters */
9223 while (*drive
<= 'Z')
9225 /* Record if this drive letter refers to a fixed drive. */
9226 fixed_drives
[DRIVE_INDEX (*drive
)] =
9227 (GetDriveType (drive
) == DRIVE_FIXED
);
9232 /* Reset the volume info cache. */
9233 volume_cache
= NULL
;
9238 shutdown_handler ensures that buffers' autosave files are
9239 up to date when the user logs off, or the system shuts down.
9242 shutdown_handler (DWORD type
)
9244 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9245 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9246 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9247 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9249 /* Shut down cleanly, making sure autosave files are up to date. */
9250 shut_down_emacs (0, Qnil
);
9253 /* Allow other handlers to handle this signal. */
9257 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9258 NT, return a handle to GDI32.DLL. */
9260 maybe_load_unicows_dll (void)
9262 if (os_subtype
== OS_9X
)
9264 HANDLE ret
= LoadLibrary ("Unicows.dll");
9267 /* These two functions are present on Windows 9X as stubs
9268 that always fail. We need the real implementations from
9269 UNICOWS.DLL, so we must call these functions through
9270 pointers, and assign the correct addresses to these
9271 pointers at program startup (see emacs.c, which calls
9272 this function early on). */
9273 pMultiByteToWideChar
=
9274 (MultiByteToWideChar_Proc
)GetProcAddress (ret
, "MultiByteToWideChar");
9275 pWideCharToMultiByte
=
9276 (WideCharToMultiByte_Proc
)GetProcAddress (ret
, "WideCharToMultiByte");
9283 button
= MessageBox (NULL
,
9284 "Emacs cannot load the UNICOWS.DLL library.\n"
9285 "This library is essential for using Emacs\n"
9286 "on this system. You need to install it.\n\n"
9287 "Emacs will exit when you click OK.",
9288 "Emacs cannot load UNICOWS.DLL",
9289 MB_ICONERROR
| MB_TASKMODAL
9290 | MB_SETFOREGROUND
| MB_OK
);
9301 /* On NT family of Windows, these two functions are always
9302 linked in, so we just assign their addresses to the 2
9303 pointers; no need for the LoadLibrary dance. */
9304 pMultiByteToWideChar
= MultiByteToWideChar
;
9305 pWideCharToMultiByte
= WideCharToMultiByte
;
9306 return LoadLibrary ("Gdi32.dll");
9311 globals_of_w32 is used to initialize those global variables that
9312 must always be initialized on startup even when the global variable
9313 initialized is non zero (see the function main in emacs.c).
9316 globals_of_w32 (void)
9318 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9320 get_process_times_fn
= (GetProcessTimes_Proc
)
9321 GetProcAddress (kernel32
, "GetProcessTimes");
9323 DEFSYM (QCloaded_from
, ":loaded-from");
9325 g_b_init_is_windows_9x
= 0;
9326 g_b_init_open_process_token
= 0;
9327 g_b_init_get_token_information
= 0;
9328 g_b_init_lookup_account_sid
= 0;
9329 g_b_init_get_sid_sub_authority
= 0;
9330 g_b_init_get_sid_sub_authority_count
= 0;
9331 g_b_init_get_security_info
= 0;
9332 g_b_init_get_file_security_w
= 0;
9333 g_b_init_get_file_security_a
= 0;
9334 g_b_init_get_security_descriptor_owner
= 0;
9335 g_b_init_get_security_descriptor_group
= 0;
9336 g_b_init_is_valid_sid
= 0;
9337 g_b_init_create_toolhelp32_snapshot
= 0;
9338 g_b_init_process32_first
= 0;
9339 g_b_init_process32_next
= 0;
9340 g_b_init_open_thread_token
= 0;
9341 g_b_init_impersonate_self
= 0;
9342 g_b_init_revert_to_self
= 0;
9343 g_b_init_get_process_memory_info
= 0;
9344 g_b_init_get_process_working_set_size
= 0;
9345 g_b_init_global_memory_status
= 0;
9346 g_b_init_global_memory_status_ex
= 0;
9347 g_b_init_equal_sid
= 0;
9348 g_b_init_copy_sid
= 0;
9349 g_b_init_get_length_sid
= 0;
9350 g_b_init_get_native_system_info
= 0;
9351 g_b_init_get_system_times
= 0;
9352 g_b_init_create_symbolic_link_w
= 0;
9353 g_b_init_create_symbolic_link_a
= 0;
9354 g_b_init_get_security_descriptor_dacl
= 0;
9355 g_b_init_convert_sd_to_sddl
= 0;
9356 g_b_init_convert_sddl_to_sd
= 0;
9357 g_b_init_is_valid_security_descriptor
= 0;
9358 g_b_init_set_file_security_w
= 0;
9359 g_b_init_set_file_security_a
= 0;
9360 g_b_init_set_named_security_info_w
= 0;
9361 g_b_init_set_named_security_info_a
= 0;
9362 g_b_init_get_adapters_info
= 0;
9363 g_b_init_compare_string_w
= 0;
9364 num_of_processors
= 0;
9365 /* The following sets a handler for shutdown notifications for
9366 console apps. This actually applies to Emacs in both console and
9367 GUI modes, since we had to fool windows into thinking emacs is a
9368 console application to get console mode to work. */
9369 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9371 /* "None" is the default group name on standalone workstations. */
9372 strcpy (dflt_group_name
, "None");
9374 /* Reset, in case it has some value inherited from dump time. */
9375 w32_stat_get_owner_group
= 0;
9377 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9378 (a.k.a. "wide") APIs to invoke functions that accept file
9380 if (is_windows_9x ())
9381 w32_unicode_filenames
= 0;
9383 w32_unicode_filenames
= 1;
9386 extern void dynlib_reset_last_error (void);
9387 dynlib_reset_last_error ();
9391 /* For make-serial-process */
9393 serial_open (Lisp_Object port_obj
)
9395 char *port
= SSDATA (port_obj
);
9400 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9401 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9402 if (hnd
== INVALID_HANDLE_VALUE
)
9403 error ("Could not open %s", port
);
9404 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9406 error ("Could not open %s", port
);
9410 error ("Could not create child process");
9412 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9413 fd_info
[ fd
].hnd
= hnd
;
9414 fd_info
[ fd
].flags
|=
9415 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9416 if (fd_info
[ fd
].cp
!= NULL
)
9418 error ("fd_info[fd = %d] is already in use", fd
);
9420 fd_info
[ fd
].cp
= cp
;
9421 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9422 if (cp
->ovl_read
.hEvent
== NULL
)
9423 error ("Could not create read event");
9424 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9425 if (cp
->ovl_write
.hEvent
== NULL
)
9426 error ("Could not create write event");
9431 /* For serial-process-configure */
9433 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9435 Lisp_Object childp2
= Qnil
;
9436 Lisp_Object tem
= Qnil
;
9440 char summary
[4] = "???"; /* This usually becomes "8N1". */
9442 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9443 error ("Not a serial process");
9444 hnd
= fd_info
[ p
->outfd
].hnd
;
9446 childp2
= Fcopy_sequence (p
->childp
);
9448 /* Initialize timeouts for blocking read and blocking write. */
9449 if (!GetCommTimeouts (hnd
, &ct
))
9450 error ("GetCommTimeouts() failed");
9451 ct
.ReadIntervalTimeout
= 0;
9452 ct
.ReadTotalTimeoutMultiplier
= 0;
9453 ct
.ReadTotalTimeoutConstant
= 0;
9454 ct
.WriteTotalTimeoutMultiplier
= 0;
9455 ct
.WriteTotalTimeoutConstant
= 0;
9456 if (!SetCommTimeouts (hnd
, &ct
))
9457 error ("SetCommTimeouts() failed");
9458 /* Read port attributes and prepare default configuration. */
9459 memset (&dcb
, 0, sizeof (dcb
));
9460 dcb
.DCBlength
= sizeof (DCB
);
9461 if (!GetCommState (hnd
, &dcb
))
9462 error ("GetCommState() failed");
9465 dcb
.fAbortOnError
= FALSE
;
9466 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9471 /* Configure speed. */
9472 if (!NILP (Fplist_member (contact
, QCspeed
)))
9473 tem
= Fplist_get (contact
, QCspeed
);
9475 tem
= Fplist_get (p
->childp
, QCspeed
);
9477 dcb
.BaudRate
= XINT (tem
);
9478 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9480 /* Configure bytesize. */
9481 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9482 tem
= Fplist_get (contact
, QCbytesize
);
9484 tem
= Fplist_get (p
->childp
, QCbytesize
);
9486 tem
= make_number (8);
9488 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9489 error (":bytesize must be nil (8), 7, or 8");
9490 dcb
.ByteSize
= XINT (tem
);
9491 summary
[0] = XINT (tem
) + '0';
9492 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9494 /* Configure parity. */
9495 if (!NILP (Fplist_member (contact
, QCparity
)))
9496 tem
= Fplist_get (contact
, QCparity
);
9498 tem
= Fplist_get (p
->childp
, QCparity
);
9499 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9500 error (":parity must be nil (no parity), `even', or `odd'");
9501 dcb
.fParity
= FALSE
;
9502 dcb
.Parity
= NOPARITY
;
9503 dcb
.fErrorChar
= FALSE
;
9508 else if (EQ (tem
, Qeven
))
9512 dcb
.Parity
= EVENPARITY
;
9513 dcb
.fErrorChar
= TRUE
;
9515 else if (EQ (tem
, Qodd
))
9519 dcb
.Parity
= ODDPARITY
;
9520 dcb
.fErrorChar
= TRUE
;
9522 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9524 /* Configure stopbits. */
9525 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9526 tem
= Fplist_get (contact
, QCstopbits
);
9528 tem
= Fplist_get (p
->childp
, QCstopbits
);
9530 tem
= make_number (1);
9532 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9533 error (":stopbits must be nil (1 stopbit), 1, or 2");
9534 summary
[2] = XINT (tem
) + '0';
9535 if (XINT (tem
) == 1)
9536 dcb
.StopBits
= ONESTOPBIT
;
9537 else if (XINT (tem
) == 2)
9538 dcb
.StopBits
= TWOSTOPBITS
;
9539 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9541 /* Configure flowcontrol. */
9542 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9543 tem
= Fplist_get (contact
, QCflowcontrol
);
9545 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9546 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9547 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9548 dcb
.fOutxCtsFlow
= FALSE
;
9549 dcb
.fOutxDsrFlow
= FALSE
;
9550 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9551 dcb
.fDsrSensitivity
= FALSE
;
9552 dcb
.fTXContinueOnXoff
= FALSE
;
9555 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9556 dcb
.XonChar
= 17; /* Control-Q */
9557 dcb
.XoffChar
= 19; /* Control-S */
9560 /* Already configured. */
9562 else if (EQ (tem
, Qhw
))
9564 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9565 dcb
.fOutxCtsFlow
= TRUE
;
9567 else if (EQ (tem
, Qsw
))
9572 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9574 /* Activate configuration. */
9575 if (!SetCommState (hnd
, &dcb
))
9576 error ("SetCommState() failed");
9578 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9579 pset_childp (p
, childp2
);
9582 /* For make-pipe-process */
9584 register_aux_fd (int infd
)
9590 error ("Could not create child process");
9592 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9594 if (fd_info
[ infd
].cp
!= NULL
)
9596 error ("fd_info[fd = %d] is already in use", infd
);
9598 fd_info
[ infd
].cp
= cp
;
9599 fd_info
[ infd
].hnd
= (HANDLE
) _get_osfhandle (infd
);
9605 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9608 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9609 int fd
= process
->infd
;
9611 n
= sys_read (fd
, (char*)buf
, sz
);
9618 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9619 if (err
== EWOULDBLOCK
)
9622 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9628 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9630 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9631 int fd
= process
->outfd
;
9632 ssize_t n
= sys_write (fd
, buf
, sz
);
9634 /* 0 or more bytes written means everything went fine. */
9638 /* Negative bytes written means we got an error in errno.
9639 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9640 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9641 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9645 #endif /* HAVE_GNUTLS */