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 SHELL */
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 */
229 #include "w32common.h"
231 #include "w32select.h"
233 #include "dispextern.h" /* for xstrcasecmp */
234 #include "coding.h" /* for Vlocale_coding_system */
236 #include "careadlinkat.h"
237 #include "allocator.h"
239 /* For serial_configure and serial_open. */
242 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
243 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
245 void globals_of_w32 (void);
246 static DWORD
get_rid (PSID
);
247 static int is_symlink (const char *);
248 static char * chase_symlinks (const char *);
249 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
250 static int restore_privilege (TOKEN_PRIVILEGES
*);
251 static BOOL WINAPI
revert_to_self (void);
253 static int sys_access (const char *, int);
254 extern void *e_malloc (size_t);
255 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
256 struct timespec
*, void *);
257 extern int sys_dup (int);
262 /* Initialization states.
264 WARNING: If you add any more such variables for additional APIs,
265 you MUST add initialization for them to globals_of_w32
266 below. This is because these variables might get set
267 to non-NULL values during dumping, but the dumped Emacs
268 cannot reuse those values, because it could be run on a
269 different version of the OS, where API addresses are
271 static BOOL g_b_init_is_windows_9x
;
272 static BOOL g_b_init_open_process_token
;
273 static BOOL g_b_init_get_token_information
;
274 static BOOL g_b_init_lookup_account_sid
;
275 static BOOL g_b_init_get_sid_sub_authority
;
276 static BOOL g_b_init_get_sid_sub_authority_count
;
277 static BOOL g_b_init_get_security_info
;
278 static BOOL g_b_init_get_file_security_w
;
279 static BOOL g_b_init_get_file_security_a
;
280 static BOOL g_b_init_get_security_descriptor_owner
;
281 static BOOL g_b_init_get_security_descriptor_group
;
282 static BOOL g_b_init_is_valid_sid
;
283 static BOOL g_b_init_create_toolhelp32_snapshot
;
284 static BOOL g_b_init_process32_first
;
285 static BOOL g_b_init_process32_next
;
286 static BOOL g_b_init_open_thread_token
;
287 static BOOL g_b_init_impersonate_self
;
288 static BOOL g_b_init_revert_to_self
;
289 static BOOL g_b_init_get_process_memory_info
;
290 static BOOL g_b_init_get_process_working_set_size
;
291 static BOOL g_b_init_global_memory_status
;
292 static BOOL g_b_init_global_memory_status_ex
;
293 static BOOL g_b_init_get_length_sid
;
294 static BOOL g_b_init_equal_sid
;
295 static BOOL g_b_init_copy_sid
;
296 static BOOL g_b_init_get_native_system_info
;
297 static BOOL g_b_init_get_system_times
;
298 static BOOL g_b_init_create_symbolic_link_w
;
299 static BOOL g_b_init_create_symbolic_link_a
;
300 static BOOL g_b_init_get_security_descriptor_dacl
;
301 static BOOL g_b_init_convert_sd_to_sddl
;
302 static BOOL g_b_init_convert_sddl_to_sd
;
303 static BOOL g_b_init_is_valid_security_descriptor
;
304 static BOOL g_b_init_set_file_security_w
;
305 static BOOL g_b_init_set_file_security_a
;
306 static BOOL g_b_init_set_named_security_info_w
;
307 static BOOL g_b_init_set_named_security_info_a
;
308 static BOOL g_b_init_get_adapters_info
;
310 BOOL g_b_init_compare_string_w
;
313 BEGIN: Wrapper functions around OpenProcessToken
314 and other functions in advapi32.dll that are only
315 supported in Windows NT / 2k / XP
317 /* ** Function pointer typedefs ** */
318 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
319 HANDLE ProcessHandle
,
321 PHANDLE TokenHandle
);
322 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
324 TOKEN_INFORMATION_CLASS TokenInformationClass
,
325 LPVOID TokenInformation
,
326 DWORD TokenInformationLength
,
327 PDWORD ReturnLength
);
328 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
329 HANDLE process_handle
,
330 LPFILETIME creation_time
,
331 LPFILETIME exit_time
,
332 LPFILETIME kernel_time
,
333 LPFILETIME user_time
);
335 GetProcessTimes_Proc get_process_times_fn
= NULL
;
338 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
340 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
342 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
343 LPCTSTR lpSystemName
,
348 LPDWORD cbDomainName
,
349 PSID_NAME_USE peUse
);
350 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
353 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
355 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
357 SE_OBJECT_TYPE ObjectType
,
358 SECURITY_INFORMATION SecurityInfo
,
363 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
364 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
366 SECURITY_INFORMATION RequestedInformation
,
367 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
369 LPDWORD lpnLengthNeeded
);
370 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
372 SECURITY_INFORMATION RequestedInformation
,
373 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
375 LPDWORD lpnLengthNeeded
);
376 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
378 SECURITY_INFORMATION SecurityInformation
,
379 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
380 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
382 SECURITY_INFORMATION SecurityInformation
,
383 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
384 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
385 LPCWSTR lpObjectName
,
386 SE_OBJECT_TYPE ObjectType
,
387 SECURITY_INFORMATION SecurityInformation
,
392 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
394 SE_OBJECT_TYPE ObjectType
,
395 SECURITY_INFORMATION SecurityInformation
,
400 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
401 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
403 LPBOOL lpbOwnerDefaulted
);
404 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
405 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
407 LPBOOL lpbGroupDefaulted
);
408 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
409 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
410 LPBOOL lpbDaclPresent
,
412 LPBOOL lpbDaclDefaulted
);
413 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
415 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
417 DWORD th32ProcessID
);
418 typedef BOOL (WINAPI
* Process32First_Proc
) (
420 LPPROCESSENTRY32 lppe
);
421 typedef BOOL (WINAPI
* Process32Next_Proc
) (
423 LPPROCESSENTRY32 lppe
);
424 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
428 PHANDLE TokenHandle
);
429 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
430 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
431 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
432 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
434 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
436 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
438 PSIZE_T lpMinimumWorkingSetSize
,
439 PSIZE_T lpMaximumWorkingSetSize
);
440 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
441 LPMEMORYSTATUS lpBuffer
);
442 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
443 LPMEMORY_STATUS_EX lpBuffer
);
444 typedef BOOL (WINAPI
* CopySid_Proc
) (
445 DWORD nDestinationSidLength
,
446 PSID pDestinationSid
,
448 typedef BOOL (WINAPI
* EqualSid_Proc
) (
451 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
453 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
454 LPSYSTEM_INFO lpSystemInfo
);
455 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
456 LPFILETIME lpIdleTime
,
457 LPFILETIME lpKernelTime
,
458 LPFILETIME lpUserTime
);
459 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
460 LPCWSTR lpSymlinkFileName
,
461 LPCWSTR lpTargetFileName
,
463 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
464 LPCSTR lpSymlinkFileName
,
465 LPCSTR lpTargetFileName
,
467 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
468 LPCTSTR StringSecurityDescriptor
,
469 DWORD StringSDRevision
,
470 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
471 PULONG SecurityDescriptorSize
);
472 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
473 PSECURITY_DESCRIPTOR SecurityDescriptor
,
474 DWORD RequestedStringSDRevision
,
475 SECURITY_INFORMATION SecurityInformation
,
476 LPTSTR
*StringSecurityDescriptor
,
477 PULONG StringSecurityDescriptorLen
);
478 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
479 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
480 PIP_ADAPTER_INFO pAdapterInfo
,
483 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
484 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
486 /* ** A utility function ** */
490 static BOOL s_b_ret
= 0;
491 OSVERSIONINFO os_ver
;
492 if (g_b_init_is_windows_9x
== 0)
494 g_b_init_is_windows_9x
= 1;
495 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
496 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
497 if (GetVersionEx (&os_ver
))
499 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
505 static Lisp_Object
ltime (ULONGLONG
);
507 /* Get total user and system times for get-internal-run-time.
508 Returns a list of integers if the times are provided by the OS
509 (NT derivatives), otherwise it returns the result of current-time. */
511 w32_get_internal_run_time (void)
513 if (get_process_times_fn
)
515 FILETIME create
, exit
, kernel
, user
;
516 HANDLE proc
= GetCurrentProcess ();
517 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
519 LARGE_INTEGER user_int
, kernel_int
, total
;
520 user_int
.LowPart
= user
.dwLowDateTime
;
521 user_int
.HighPart
= user
.dwHighDateTime
;
522 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
523 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
524 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
525 return ltime (total
.QuadPart
);
529 return Fcurrent_time ();
532 /* ** The wrapper functions ** */
535 open_process_token (HANDLE ProcessHandle
,
539 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
540 HMODULE hm_advapi32
= NULL
;
541 if (is_windows_9x () == TRUE
)
545 if (g_b_init_open_process_token
== 0)
547 g_b_init_open_process_token
= 1;
548 hm_advapi32
= LoadLibrary ("Advapi32.dll");
549 s_pfn_Open_Process_Token
=
550 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
552 if (s_pfn_Open_Process_Token
== NULL
)
557 s_pfn_Open_Process_Token (
565 get_token_information (HANDLE TokenHandle
,
566 TOKEN_INFORMATION_CLASS TokenInformationClass
,
567 LPVOID TokenInformation
,
568 DWORD TokenInformationLength
,
571 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
572 HMODULE hm_advapi32
= NULL
;
573 if (is_windows_9x () == TRUE
)
577 if (g_b_init_get_token_information
== 0)
579 g_b_init_get_token_information
= 1;
580 hm_advapi32
= LoadLibrary ("Advapi32.dll");
581 s_pfn_Get_Token_Information
=
582 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
584 if (s_pfn_Get_Token_Information
== NULL
)
589 s_pfn_Get_Token_Information (
591 TokenInformationClass
,
593 TokenInformationLength
,
599 lookup_account_sid (LPCTSTR lpSystemName
,
604 LPDWORD cbDomainName
,
607 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
608 HMODULE hm_advapi32
= NULL
;
609 if (is_windows_9x () == TRUE
)
613 if (g_b_init_lookup_account_sid
== 0)
615 g_b_init_lookup_account_sid
= 1;
616 hm_advapi32
= LoadLibrary ("Advapi32.dll");
617 s_pfn_Lookup_Account_Sid
=
618 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
620 if (s_pfn_Lookup_Account_Sid
== NULL
)
625 s_pfn_Lookup_Account_Sid (
637 get_sid_sub_authority (PSID pSid
, DWORD n
)
639 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
640 static DWORD zero
= 0U;
641 HMODULE hm_advapi32
= NULL
;
642 if (is_windows_9x () == TRUE
)
646 if (g_b_init_get_sid_sub_authority
== 0)
648 g_b_init_get_sid_sub_authority
= 1;
649 hm_advapi32
= LoadLibrary ("Advapi32.dll");
650 s_pfn_Get_Sid_Sub_Authority
=
651 (GetSidSubAuthority_Proc
) GetProcAddress (
652 hm_advapi32
, "GetSidSubAuthority");
654 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
658 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
662 get_sid_sub_authority_count (PSID pSid
)
664 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
665 static UCHAR zero
= 0U;
666 HMODULE hm_advapi32
= NULL
;
667 if (is_windows_9x () == TRUE
)
671 if (g_b_init_get_sid_sub_authority_count
== 0)
673 g_b_init_get_sid_sub_authority_count
= 1;
674 hm_advapi32
= LoadLibrary ("Advapi32.dll");
675 s_pfn_Get_Sid_Sub_Authority_Count
=
676 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
677 hm_advapi32
, "GetSidSubAuthorityCount");
679 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
683 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
687 get_security_info (HANDLE handle
,
688 SE_OBJECT_TYPE ObjectType
,
689 SECURITY_INFORMATION SecurityInfo
,
694 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
696 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
697 HMODULE hm_advapi32
= NULL
;
698 if (is_windows_9x () == TRUE
)
702 if (g_b_init_get_security_info
== 0)
704 g_b_init_get_security_info
= 1;
705 hm_advapi32
= LoadLibrary ("Advapi32.dll");
706 s_pfn_Get_Security_Info
=
707 (GetSecurityInfo_Proc
) GetProcAddress (
708 hm_advapi32
, "GetSecurityInfo");
710 if (s_pfn_Get_Security_Info
== NULL
)
714 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
715 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
716 ppSecurityDescriptor
));
720 get_file_security (const char *lpFileName
,
721 SECURITY_INFORMATION RequestedInformation
,
722 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
724 LPDWORD lpnLengthNeeded
)
726 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
727 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
728 HMODULE hm_advapi32
= NULL
;
729 if (is_windows_9x () == TRUE
)
734 if (w32_unicode_filenames
)
736 wchar_t filename_w
[MAX_PATH
];
738 if (g_b_init_get_file_security_w
== 0)
740 g_b_init_get_file_security_w
= 1;
741 hm_advapi32
= LoadLibrary ("Advapi32.dll");
742 s_pfn_Get_File_SecurityW
=
743 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
746 if (s_pfn_Get_File_SecurityW
== NULL
)
751 filename_to_utf16 (lpFileName
, filename_w
);
752 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
753 pSecurityDescriptor
, nLength
,
758 char filename_a
[MAX_PATH
];
760 if (g_b_init_get_file_security_a
== 0)
762 g_b_init_get_file_security_a
= 1;
763 hm_advapi32
= LoadLibrary ("Advapi32.dll");
764 s_pfn_Get_File_SecurityA
=
765 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
768 if (s_pfn_Get_File_SecurityA
== NULL
)
773 filename_to_ansi (lpFileName
, filename_a
);
774 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
775 pSecurityDescriptor
, nLength
,
781 set_file_security (const char *lpFileName
,
782 SECURITY_INFORMATION SecurityInformation
,
783 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
785 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
786 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
787 HMODULE hm_advapi32
= NULL
;
788 if (is_windows_9x () == TRUE
)
793 if (w32_unicode_filenames
)
795 wchar_t filename_w
[MAX_PATH
];
797 if (g_b_init_set_file_security_w
== 0)
799 g_b_init_set_file_security_w
= 1;
800 hm_advapi32
= LoadLibrary ("Advapi32.dll");
801 s_pfn_Set_File_SecurityW
=
802 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
805 if (s_pfn_Set_File_SecurityW
== NULL
)
810 filename_to_utf16 (lpFileName
, filename_w
);
811 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
812 pSecurityDescriptor
));
816 char filename_a
[MAX_PATH
];
818 if (g_b_init_set_file_security_a
== 0)
820 g_b_init_set_file_security_a
= 1;
821 hm_advapi32
= LoadLibrary ("Advapi32.dll");
822 s_pfn_Set_File_SecurityA
=
823 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
826 if (s_pfn_Set_File_SecurityA
== NULL
)
831 filename_to_ansi (lpFileName
, filename_a
);
832 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
833 pSecurityDescriptor
));
838 set_named_security_info (LPCTSTR lpObjectName
,
839 SE_OBJECT_TYPE ObjectType
,
840 SECURITY_INFORMATION SecurityInformation
,
846 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
847 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
848 HMODULE hm_advapi32
= NULL
;
849 if (is_windows_9x () == TRUE
)
854 if (w32_unicode_filenames
)
856 wchar_t filename_w
[MAX_PATH
];
858 if (g_b_init_set_named_security_info_w
== 0)
860 g_b_init_set_named_security_info_w
= 1;
861 hm_advapi32
= LoadLibrary ("Advapi32.dll");
862 s_pfn_Set_Named_Security_InfoW
=
863 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
864 "SetNamedSecurityInfoW");
866 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
871 filename_to_utf16 (lpObjectName
, filename_w
);
872 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
873 SecurityInformation
, psidOwner
,
874 psidGroup
, pDacl
, pSacl
));
878 char filename_a
[MAX_PATH
];
880 if (g_b_init_set_named_security_info_a
== 0)
882 g_b_init_set_named_security_info_a
= 1;
883 hm_advapi32
= LoadLibrary ("Advapi32.dll");
884 s_pfn_Set_Named_Security_InfoA
=
885 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
886 "SetNamedSecurityInfoA");
888 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
893 filename_to_ansi (lpObjectName
, filename_a
);
894 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
895 SecurityInformation
, psidOwner
,
896 psidGroup
, pDacl
, pSacl
));
901 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
903 LPBOOL lpbOwnerDefaulted
)
905 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
906 HMODULE hm_advapi32
= NULL
;
907 if (is_windows_9x () == TRUE
)
912 if (g_b_init_get_security_descriptor_owner
== 0)
914 g_b_init_get_security_descriptor_owner
= 1;
915 hm_advapi32
= LoadLibrary ("Advapi32.dll");
916 s_pfn_Get_Security_Descriptor_Owner
=
917 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
918 hm_advapi32
, "GetSecurityDescriptorOwner");
920 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
925 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
930 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
932 LPBOOL lpbGroupDefaulted
)
934 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
935 HMODULE hm_advapi32
= NULL
;
936 if (is_windows_9x () == TRUE
)
941 if (g_b_init_get_security_descriptor_group
== 0)
943 g_b_init_get_security_descriptor_group
= 1;
944 hm_advapi32
= LoadLibrary ("Advapi32.dll");
945 s_pfn_Get_Security_Descriptor_Group
=
946 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
947 hm_advapi32
, "GetSecurityDescriptorGroup");
949 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
954 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
959 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
960 LPBOOL lpbDaclPresent
,
962 LPBOOL lpbDaclDefaulted
)
964 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
965 HMODULE hm_advapi32
= NULL
;
966 if (is_windows_9x () == TRUE
)
971 if (g_b_init_get_security_descriptor_dacl
== 0)
973 g_b_init_get_security_descriptor_dacl
= 1;
974 hm_advapi32
= LoadLibrary ("Advapi32.dll");
975 s_pfn_Get_Security_Descriptor_Dacl
=
976 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
977 hm_advapi32
, "GetSecurityDescriptorDacl");
979 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
984 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
985 lpbDaclPresent
, pDacl
,
990 is_valid_sid (PSID sid
)
992 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
993 HMODULE hm_advapi32
= NULL
;
994 if (is_windows_9x () == TRUE
)
998 if (g_b_init_is_valid_sid
== 0)
1000 g_b_init_is_valid_sid
= 1;
1001 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1002 s_pfn_Is_Valid_Sid
=
1003 (IsValidSid_Proc
) GetProcAddress (
1004 hm_advapi32
, "IsValidSid");
1006 if (s_pfn_Is_Valid_Sid
== NULL
)
1010 return (s_pfn_Is_Valid_Sid (sid
));
1014 equal_sid (PSID sid1
, PSID sid2
)
1016 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1017 HMODULE hm_advapi32
= NULL
;
1018 if (is_windows_9x () == TRUE
)
1022 if (g_b_init_equal_sid
== 0)
1024 g_b_init_equal_sid
= 1;
1025 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1027 (EqualSid_Proc
) GetProcAddress (
1028 hm_advapi32
, "EqualSid");
1030 if (s_pfn_Equal_Sid
== NULL
)
1034 return (s_pfn_Equal_Sid (sid1
, sid2
));
1038 get_length_sid (PSID sid
)
1040 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1041 HMODULE hm_advapi32
= NULL
;
1042 if (is_windows_9x () == TRUE
)
1046 if (g_b_init_get_length_sid
== 0)
1048 g_b_init_get_length_sid
= 1;
1049 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1050 s_pfn_Get_Length_Sid
=
1051 (GetLengthSid_Proc
) GetProcAddress (
1052 hm_advapi32
, "GetLengthSid");
1054 if (s_pfn_Get_Length_Sid
== NULL
)
1058 return (s_pfn_Get_Length_Sid (sid
));
1062 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1064 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1065 HMODULE hm_advapi32
= NULL
;
1066 if (is_windows_9x () == TRUE
)
1070 if (g_b_init_copy_sid
== 0)
1072 g_b_init_copy_sid
= 1;
1073 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1075 (CopySid_Proc
) GetProcAddress (
1076 hm_advapi32
, "CopySid");
1078 if (s_pfn_Copy_Sid
== NULL
)
1082 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1086 END: Wrapper functions around OpenProcessToken
1087 and other functions in advapi32.dll that are only
1088 supported in Windows NT / 2k / XP
1092 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1094 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1095 if (is_windows_9x () != TRUE
)
1097 if (g_b_init_get_native_system_info
== 0)
1099 g_b_init_get_native_system_info
= 1;
1100 s_pfn_Get_Native_System_Info
=
1101 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1102 "GetNativeSystemInfo");
1104 if (s_pfn_Get_Native_System_Info
!= NULL
)
1105 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1108 lpSystemInfo
->dwNumberOfProcessors
= -1;
1112 get_system_times (LPFILETIME lpIdleTime
,
1113 LPFILETIME lpKernelTime
,
1114 LPFILETIME lpUserTime
)
1116 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1117 if (is_windows_9x () == TRUE
)
1121 if (g_b_init_get_system_times
== 0)
1123 g_b_init_get_system_times
= 1;
1124 s_pfn_Get_System_times
=
1125 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1128 if (s_pfn_Get_System_times
== NULL
)
1130 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1133 static BOOLEAN WINAPI
1134 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1135 LPCSTR lpTargetFileName
,
1138 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1139 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1142 if (is_windows_9x () == TRUE
)
1147 if (w32_unicode_filenames
)
1149 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1151 if (g_b_init_create_symbolic_link_w
== 0)
1153 g_b_init_create_symbolic_link_w
= 1;
1154 s_pfn_Create_Symbolic_LinkW
=
1155 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1156 "CreateSymbolicLinkW");
1158 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1164 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1165 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1166 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1167 /* If we were denied creation of the symlink, try again after
1168 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1171 TOKEN_PRIVILEGES priv_current
;
1173 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1176 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1177 restore_privilege (&priv_current
);
1184 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1186 if (g_b_init_create_symbolic_link_a
== 0)
1188 g_b_init_create_symbolic_link_a
= 1;
1189 s_pfn_Create_Symbolic_LinkA
=
1190 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1191 "CreateSymbolicLinkA");
1193 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1199 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1200 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1201 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1202 /* If we were denied creation of the symlink, try again after
1203 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1206 TOKEN_PRIVILEGES priv_current
;
1208 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1211 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1212 restore_privilege (&priv_current
);
1221 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1223 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1225 if (is_windows_9x () == TRUE
)
1231 if (g_b_init_is_valid_security_descriptor
== 0)
1233 g_b_init_is_valid_security_descriptor
= 1;
1234 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1235 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1236 "IsValidSecurityDescriptor");
1238 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1244 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1248 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1249 DWORD RequestedStringSDRevision
,
1250 SECURITY_INFORMATION SecurityInformation
,
1251 LPTSTR
*StringSecurityDescriptor
,
1252 PULONG StringSecurityDescriptorLen
)
1254 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1257 if (is_windows_9x () == TRUE
)
1263 if (g_b_init_convert_sd_to_sddl
== 0)
1265 g_b_init_convert_sd_to_sddl
= 1;
1267 s_pfn_Convert_SD_To_SDDL
=
1268 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1269 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1271 s_pfn_Convert_SD_To_SDDL
=
1272 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1273 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1276 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1282 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1283 RequestedStringSDRevision
,
1284 SecurityInformation
,
1285 StringSecurityDescriptor
,
1286 StringSecurityDescriptorLen
);
1292 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1293 DWORD StringSDRevision
,
1294 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1295 PULONG SecurityDescriptorSize
)
1297 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1300 if (is_windows_9x () == TRUE
)
1306 if (g_b_init_convert_sddl_to_sd
== 0)
1308 g_b_init_convert_sddl_to_sd
= 1;
1310 s_pfn_Convert_SDDL_To_SD
=
1311 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1312 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1314 s_pfn_Convert_SDDL_To_SD
=
1315 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1316 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1319 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1325 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1328 SecurityDescriptorSize
);
1334 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1336 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1337 HMODULE hm_iphlpapi
= NULL
;
1339 if (is_windows_9x () == TRUE
)
1340 return ERROR_NOT_SUPPORTED
;
1342 if (g_b_init_get_adapters_info
== 0)
1344 g_b_init_get_adapters_info
= 1;
1345 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1347 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1348 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1350 if (s_pfn_Get_Adapters_Info
== NULL
)
1351 return ERROR_NOT_SUPPORTED
;
1352 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1357 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1358 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1360 This is called from alloc.c:valid_pointer_p. */
1362 w32_valid_pointer_p (void *p
, int size
)
1365 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1369 unsigned char *buf
= alloca (size
);
1370 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1381 /* Here's an overview of how the Windows build supports file names
1382 that cannot be encoded by the current system codepage.
1384 From the POV of Lisp and layers of C code above the functions here,
1385 Emacs on Windows pretends that its file names are encoded in UTF-8;
1386 see encode_file and decode_file on coding.c. Any file name that is
1387 passed as a unibyte string to C functions defined here is assumed
1388 to be in UTF-8 encoding. Any file name returned by functions
1389 defined here must be in UTF-8 encoding, with only a few exceptions
1390 reserved for a couple of special cases. (Be sure to use
1391 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1392 as they can be much longer than MAX_PATH!)
1394 The UTF-8 encoded file names cannot be passed to system APIs, as
1395 Windows does not support that. Therefore, they are converted
1396 either to UTF-16 or to the ANSI codepage, depending on the value of
1397 w32-unicode-filenames, before calling any system APIs or CRT library
1398 functions. The default value of that variable is determined by the
1399 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1400 user can change that default (although I don't see why would she
1403 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1404 filename_from_utf16, and filename_from_ansi, are the workhorses of
1405 these conversions. They rely on Windows native APIs
1406 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1407 functions from coding.c here, because they allocate memory, which
1408 is a bad idea on the level of libc, which is what the functions
1409 here emulate. (If you worry about performance due to constant
1410 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1411 it was measured to take only a few microseconds on a not-so-fast
1412 machine, and second, that's exactly what the ANSI APIs we used
1413 before did anyway, because they are just thin wrappers around the
1416 The variables file-name-coding-system and default-file-name-coding-system
1417 still exist, but are actually used only when a file name needs to
1418 be converted to the ANSI codepage. This happens all the time when
1419 w32-unicode-filenames is nil, but can also happen from time to time
1420 when it is t. Otherwise, these variables have no effect on file-name
1421 encoding when w32-unicode-filenames is t; this is similar to
1422 selection-coding-system.
1424 This arrangement works very well, but it has a few gotchas and
1427 . Lisp code that encodes or decodes file names manually should
1428 normally use 'utf-8' as the coding-system on Windows,
1429 disregarding file-name-coding-system. This is a somewhat
1430 unpleasant consequence, but it cannot be avoided. Fortunately,
1431 very few Lisp packages need to do that.
1433 More generally, passing to library functions (e.g., fopen or
1434 opendir) file names already encoded in the ANSI codepage is
1435 explicitly *verboten*, as all those functions, as shadowed and
1436 emulated here, assume they will receive UTF-8 encoded file names.
1438 For the same reasons, no CRT function or Win32 API can be called
1439 directly in Emacs sources, without either converting the file
1440 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1441 some shadowing function defined here.
1443 . Environment variables stored in Vprocess_environment are encoded
1444 in the ANSI codepage, so if getenv/egetenv is used for a variable
1445 whose value is a file name or a list of directories, it needs to
1446 be converted to UTF-8, before it is used as argument to functions
1447 or decoded into a Lisp string.
1449 . File names passed to external libraries, like the image libraries
1450 and GnuTLS, need special handling. These libraries generally
1451 don't support UTF-16 or UTF-8 file names, so they must get file
1452 names encoded in the ANSI codepage. To facilitate using these
1453 libraries with file names that are not encodable in the ANSI
1454 codepage, use the function ansi_encode_filename, which will try
1455 to use the short 8+3 alias of a file name if that file name is
1456 not encodable in the ANSI codepage. See image.c and gnutls.c for
1457 examples of how this should be done.
1459 . Running subprocesses in non-ASCII directories and with non-ASCII
1460 file arguments is limited to the current codepage (even though
1461 Emacs is perfectly capable of finding an executable program file
1462 in a directory whose name cannot be encoded in the current
1463 codepage). This is because the command-line arguments are
1464 encoded _before_ they get to the w32-specific level, and the
1465 encoding is not known in advance (it doesn't have to be the
1466 current ANSI codepage), so w32proc.c functions cannot re-encode
1467 them in UTF-16. This should be fixed, but will also require
1468 changes in cmdproxy. The current limitation is not terribly bad
1469 anyway, since very few, if any, Windows console programs that are
1470 likely to be invoked by Emacs support UTF-16 encoded command
1473 . For similar reasons, server.el and emacsclient are also limited
1474 to the current ANSI codepage for now.
1476 . Emacs itself can only handle command-line arguments encoded in
1477 the current codepage.
1479 . Turning on w32-unicode-filename on Windows 9X (if it at all
1480 works) requires UNICOWS.DLL, which is thus a requirement even in
1481 non-GUI sessions, something the we previously avoided. */
1485 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1486 codepage defined by file-name-coding-system. */
1488 /* Current codepage for encoding file names. */
1489 static int file_name_codepage
;
1491 /* Produce a Windows ANSI codepage suitable for encoding file names.
1492 Return the information about that codepage in CP_INFO. */
1494 codepage_for_filenames (CPINFO
*cp_info
)
1496 /* A simple cache to avoid calling GetCPInfo every time we need to
1497 encode/decode a file name. The file-name encoding is not
1498 supposed to be changed too frequently, if ever. */
1499 static Lisp_Object last_file_name_encoding
;
1501 Lisp_Object current_encoding
;
1503 current_encoding
= Vfile_name_coding_system
;
1504 if (NILP (current_encoding
))
1505 current_encoding
= Vdefault_file_name_coding_system
;
1507 if (!EQ (last_file_name_encoding
, current_encoding
))
1509 /* Default to the current ANSI codepage. */
1510 file_name_codepage
= w32_ansi_code_page
;
1512 if (NILP (current_encoding
))
1514 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1515 char *cp
= NULL
, *end
;
1518 if (strncmp (cpname
, "cp", 2) == 0)
1520 else if (strncmp (cpname
, "windows-", 8) == 0)
1526 cpnum
= strtol (cp
, &end
, 10);
1527 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1528 file_name_codepage
= cpnum
;
1532 if (!file_name_codepage
)
1533 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1535 if (!GetCPInfo (file_name_codepage
, &cp
))
1537 file_name_codepage
= CP_ACP
;
1538 if (!GetCPInfo (file_name_codepage
, &cp
))
1545 return file_name_codepage
;
1549 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1551 int result
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1556 DWORD err
= GetLastError ();
1560 case ERROR_INVALID_FLAGS
:
1561 case ERROR_INVALID_PARAMETER
:
1564 case ERROR_INSUFFICIENT_BUFFER
:
1565 case ERROR_NO_UNICODE_TRANSLATION
:
1576 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1578 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1579 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1583 DWORD err
= GetLastError ();
1587 case ERROR_INVALID_FLAGS
:
1588 case ERROR_INVALID_PARAMETER
:
1591 case ERROR_INSUFFICIENT_BUFFER
:
1592 case ERROR_NO_UNICODE_TRANSLATION
:
1603 filename_to_ansi (const char *fn_in
, char *fn_out
)
1605 wchar_t fn_utf16
[MAX_PATH
];
1607 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1610 int codepage
= codepage_for_filenames (NULL
);
1612 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1613 fn_out
, MAX_PATH
, NULL
, NULL
);
1616 DWORD err
= GetLastError ();
1620 case ERROR_INVALID_FLAGS
:
1621 case ERROR_INVALID_PARAMETER
:
1624 case ERROR_INSUFFICIENT_BUFFER
:
1625 case ERROR_NO_UNICODE_TRANSLATION
:
1638 filename_from_ansi (const char *fn_in
, char *fn_out
)
1640 wchar_t fn_utf16
[MAX_PATH
];
1641 int codepage
= codepage_for_filenames (NULL
);
1642 int result
= pMultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1643 fn_utf16
, MAX_PATH
);
1647 DWORD err
= GetLastError ();
1651 case ERROR_INVALID_FLAGS
:
1652 case ERROR_INVALID_PARAMETER
:
1655 case ERROR_INSUFFICIENT_BUFFER
:
1656 case ERROR_NO_UNICODE_TRANSLATION
:
1663 return filename_from_utf16 (fn_utf16
, fn_out
);
1668 /* The directory where we started, in UTF-8. */
1669 static char startup_dir
[MAX_UTF8_PATH
];
1671 /* Get the current working directory. */
1673 getcwd (char *dir
, int dirsize
)
1680 if (dirsize
<= strlen (startup_dir
))
1686 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1690 /* Emacs doesn't actually change directory itself, it stays in the
1691 same directory where it was started. */
1692 strcpy (dir
, startup_dir
);
1697 /* Emulate getloadavg. */
1699 struct load_sample
{
1706 /* Number of processors on this machine. */
1707 static unsigned num_of_processors
;
1709 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1710 static struct load_sample samples
[16*60];
1711 static int first_idx
= -1, last_idx
= -1;
1712 static int max_idx
= ARRAYELTS (samples
);
1717 int next_idx
= from
+ 1;
1719 if (next_idx
>= max_idx
)
1728 int prev_idx
= from
- 1;
1731 prev_idx
= max_idx
- 1;
1737 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1739 SYSTEM_INFO sysinfo
;
1740 FILETIME ft_idle
, ft_user
, ft_kernel
;
1742 /* Initialize the number of processors on this machine. */
1743 if (num_of_processors
<= 0)
1745 get_native_system_info (&sysinfo
);
1746 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1747 if (num_of_processors
<= 0)
1749 GetSystemInfo (&sysinfo
);
1750 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1752 if (num_of_processors
<= 0)
1753 num_of_processors
= 1;
1756 /* TODO: Take into account threads that are ready to run, by
1757 sampling the "\System\Processor Queue Length" performance
1758 counter. The code below accounts only for threads that are
1759 actually running. */
1761 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1763 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1765 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1766 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1767 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1768 *idle
= uidle
.QuadPart
;
1769 *kernel
= ukernel
.QuadPart
;
1770 *user
= uuser
.QuadPart
;
1780 /* Produce the load average for a given time interval, using the
1781 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1782 1-minute, 5-minute, or 15-minute average, respectively. */
1786 double retval
= -1.0;
1789 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1790 time_t now
= samples
[last_idx
].sample_time
;
1792 if (first_idx
!= last_idx
)
1794 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1796 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1797 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1800 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1801 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1802 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1804 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1807 if (idx
== first_idx
)
1816 getloadavg (double loadavg
[], int nelem
)
1819 ULONGLONG idle
, kernel
, user
;
1820 time_t now
= time (NULL
);
1822 /* If system time jumped back for some reason, delete all samples
1823 whose time is later than the current wall-clock time. This
1824 prevents load average figures from becoming frozen for prolonged
1825 periods of time, when system time is reset backwards. */
1828 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1830 if (last_idx
== first_idx
)
1832 first_idx
= last_idx
= -1;
1835 last_idx
= buf_prev (last_idx
);
1839 /* Store another sample. We ignore samples that are less than 1 sec
1842 || (difftime (now
, samples
[last_idx
].sample_time
)
1843 >= 1.0 - 2*DBL_EPSILON
*now
))
1845 sample_system_load (&idle
, &kernel
, &user
);
1846 last_idx
= buf_next (last_idx
);
1847 samples
[last_idx
].sample_time
= now
;
1848 samples
[last_idx
].idle
= idle
;
1849 samples
[last_idx
].kernel
= kernel
;
1850 samples
[last_idx
].user
= user
;
1851 /* If the buffer has more that 15 min worth of samples, discard
1853 if (first_idx
== -1)
1854 first_idx
= last_idx
;
1855 while (first_idx
!= last_idx
1856 && (difftime (now
, samples
[first_idx
].sample_time
)
1857 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1858 first_idx
= buf_next (first_idx
);
1861 for (elem
= 0; elem
< nelem
; elem
++)
1863 double avg
= getavg (elem
);
1867 loadavg
[elem
] = avg
;
1873 /* Emulate getpwuid, getpwnam and others. */
1875 #define PASSWD_FIELD_SIZE 256
1877 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1878 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1879 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1880 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1881 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1883 static struct passwd dflt_passwd
=
1895 static char dflt_group_name
[GNLEN
+1];
1897 static struct group dflt_group
=
1899 /* When group information is not available, we return this as the
1900 group for all files. */
1908 return dflt_passwd
.pw_uid
;
1914 /* I could imagine arguing for checking to see whether the user is
1915 in the Administrators group and returning a UID of 0 for that
1916 case, but I don't know how wise that would be in the long run. */
1923 return dflt_passwd
.pw_gid
;
1933 getpwuid (unsigned uid
)
1935 if (uid
== dflt_passwd
.pw_uid
)
1936 return &dflt_passwd
;
1941 getgrgid (gid_t gid
)
1947 getpwnam (char *name
)
1951 pw
= getpwuid (getuid ());
1955 if (xstrcasecmp (name
, pw
->pw_name
))
1962 init_user_info (void)
1964 /* Find the user's real name by opening the process token and
1965 looking up the name associated with the user-sid in that token.
1967 Use the relative portion of the identifier authority value from
1968 the user-sid as the user id value (same for group id using the
1969 primary group sid from the process token). */
1971 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1972 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1973 DWORD glength
= sizeof (gname
);
1974 HANDLE token
= NULL
;
1975 SID_NAME_USE user_type
;
1976 unsigned char *buf
= NULL
;
1978 TOKEN_USER user_token
;
1979 TOKEN_PRIMARY_GROUP group_token
;
1982 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1985 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1986 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1988 buf
= xmalloc (blen
);
1989 result
= get_token_information (token
, TokenUser
,
1990 (LPVOID
)buf
, blen
, &needed
);
1993 memcpy (&user_token
, buf
, sizeof (user_token
));
1994 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1996 domain
, &dlength
, &user_type
);
2004 strcpy (dflt_passwd
.pw_name
, uname
);
2005 /* Determine a reasonable uid value. */
2006 if (xstrcasecmp ("administrator", uname
) == 0)
2008 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2009 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2013 /* Use the last sub-authority value of the RID, the relative
2014 portion of the SID, as user/group ID. */
2015 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2017 /* Get group id and name. */
2018 result
= get_token_information (token
, TokenPrimaryGroup
,
2019 (LPVOID
)buf
, blen
, &needed
);
2020 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2022 buf
= xrealloc (buf
, blen
= needed
);
2023 result
= get_token_information (token
, TokenPrimaryGroup
,
2024 (LPVOID
)buf
, blen
, &needed
);
2028 memcpy (&group_token
, buf
, sizeof (group_token
));
2029 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2030 dlength
= sizeof (domain
);
2031 /* If we can get at the real Primary Group name, use that.
2032 Otherwise, the default group name was already set to
2033 "None" in globals_of_w32. */
2034 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2035 gname
, &glength
, NULL
, &dlength
,
2037 strcpy (dflt_group_name
, gname
);
2040 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2043 /* If security calls are not supported (presumably because we
2044 are running under Windows 9X), fallback to this: */
2045 else if (GetUserName (uname
, &ulength
))
2047 strcpy (dflt_passwd
.pw_name
, uname
);
2048 if (xstrcasecmp ("administrator", uname
) == 0)
2049 dflt_passwd
.pw_uid
= 0;
2051 dflt_passwd
.pw_uid
= 123;
2052 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2056 strcpy (dflt_passwd
.pw_name
, "unknown");
2057 dflt_passwd
.pw_uid
= 123;
2058 dflt_passwd
.pw_gid
= 123;
2060 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2062 /* Set dir and shell from environment variables. */
2063 if (w32_unicode_filenames
)
2065 wchar_t *home
= _wgetenv (L
"HOME");
2066 wchar_t *shell
= _wgetenv (L
"SHELL");
2068 /* Ensure HOME and SHELL are defined. */
2073 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2074 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2078 char *home
= getenv ("HOME");
2079 char *shell
= getenv ("SHELL");
2085 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2086 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2091 CloseHandle (token
);
2097 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2098 return ((rand () << 15) | rand ());
2107 /* Return the maximum length in bytes of a multibyte character
2108 sequence encoded in the current ANSI codepage. This is required to
2109 correctly walk the encoded file names one character at a time. */
2111 max_filename_mbslen (void)
2115 codepage_for_filenames (&cp_info
);
2116 return cp_info
.MaxCharSize
;
2119 /* Normalize filename by converting in-place all of its path
2120 separators to the separator specified by PATH_SEP. */
2123 normalize_filename (register char *fp
, char path_sep
)
2127 /* Always lower-case drive letters a-z, even if the filesystem
2128 preserves case in filenames.
2129 This is so filenames can be compared by string comparison
2130 functions that are case-sensitive. Even case-preserving filesystems
2131 do not distinguish case in drive letters. */
2134 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2142 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2148 /* Destructively turn backslashes into slashes. */
2150 dostounix_filename (register char *p
)
2152 normalize_filename (p
, '/');
2155 /* Destructively turn slashes into backslashes. */
2157 unixtodos_filename (register char *p
)
2159 normalize_filename (p
, '\\');
2162 /* Remove all CR's that are followed by a LF.
2163 (From msdos.c...probably should figure out a way to share it,
2164 although this code isn't going to ever change.) */
2166 crlf_to_lf (register int n
, register unsigned char *buf
)
2168 unsigned char *np
= buf
;
2169 unsigned char *startp
= buf
;
2170 unsigned char *endp
= buf
+ n
;
2174 while (buf
< endp
- 1)
2178 if (*(++buf
) != 0x0a)
2189 /* Parse the root part of file name, if present. Return length and
2190 optionally store pointer to char after root. */
2192 parse_root (const char * name
, const char ** pPath
)
2194 const char * start
= name
;
2199 /* find the root name of the volume if given */
2200 if (isalpha (name
[0]) && name
[1] == ':')
2202 /* skip past drive specifier */
2204 if (IS_DIRECTORY_SEP (name
[0]))
2207 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2214 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2219 if (IS_DIRECTORY_SEP (name
[0]))
2226 return name
- start
;
2229 /* Get long base name for name; name is assumed to be absolute. */
2231 get_long_basename (char * name
, char * buf
, int size
)
2233 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2234 char fname_utf8
[MAX_UTF8_PATH
];
2238 /* Must be valid filename, no wild cards or other invalid characters. */
2239 if (strpbrk (name
, "*?|<>\""))
2242 if (w32_unicode_filenames
)
2244 wchar_t fname_utf16
[MAX_PATH
];
2245 WIN32_FIND_DATAW find_data_wide
;
2247 filename_to_utf16 (name
, fname_utf16
);
2248 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2249 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2250 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2254 char fname_ansi
[MAX_PATH
];
2255 WIN32_FIND_DATAA find_data_ansi
;
2257 filename_to_ansi (name
, fname_ansi
);
2258 /* If the ANSI name includes ? characters, it is not encodable
2259 in the ANSI codepage. In that case, we deliver the question
2260 marks to the caller; calling FindFirstFileA in this case
2261 could return some unrelated file name in the same
2263 if (_mbspbrk (fname_ansi
, "?"))
2265 /* Find the basename of fname_ansi. */
2266 char *p
= strrchr (fname_ansi
, '\\');
2272 cstatus
= filename_from_ansi (p
, fname_utf8
);
2276 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2277 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2278 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2282 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2283 memcpy (buf
, fname_utf8
, len
+ 1);
2287 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2288 FindClose (dir_handle
);
2293 /* Get long name for file, if possible (assumed to be absolute). */
2295 w32_get_long_filename (const char * name
, char * buf
, int size
)
2300 char full
[ MAX_UTF8_PATH
];
2303 len
= strlen (name
);
2304 if (len
>= MAX_UTF8_PATH
)
2307 /* Use local copy for destructive modification. */
2308 memcpy (full
, name
, len
+1);
2309 unixtodos_filename (full
);
2311 /* Copy root part verbatim. */
2312 len
= parse_root (full
, (const char **)&p
);
2313 memcpy (o
, full
, len
);
2318 while (p
!= NULL
&& *p
)
2321 p
= strchr (q
, '\\');
2323 len
= get_long_basename (full
, o
, size
);
2346 w32_get_short_filename (const char * name
, char * buf
, int size
)
2348 if (w32_unicode_filenames
)
2350 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2351 unsigned int retval
;
2353 filename_to_utf16 (name
, name_utf16
);
2354 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2355 if (retval
&& retval
< size
)
2356 filename_from_utf16 (short_name
, buf
);
2361 char name_ansi
[MAX_PATH
];
2363 filename_to_ansi (name
, name_ansi
);
2364 return GetShortPathNameA (name_ansi
, buf
, size
);
2368 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2369 MS-Windows ANSI codepage. If FILENAME includes characters not
2370 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2371 if it exists. This is needed because the w32 build wants to
2372 support file names outside of the system locale, but image
2373 libraries typically don't support wide (a.k.a. "Unicode") APIs
2374 required for that. */
2377 ansi_encode_filename (Lisp_Object filename
)
2379 Lisp_Object encoded_filename
;
2380 char fname
[MAX_PATH
];
2382 filename_to_ansi (SSDATA (filename
), fname
);
2383 if (_mbspbrk (fname
, "?"))
2385 char shortname
[MAX_PATH
];
2387 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2389 dostounix_filename (shortname
);
2390 encoded_filename
= build_string (shortname
);
2393 encoded_filename
= build_unibyte_string (fname
);
2396 encoded_filename
= build_unibyte_string (fname
);
2397 return encoded_filename
;
2401 is_unc_volume (const char *filename
)
2403 const char *ptr
= filename
;
2405 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2408 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2414 /* Emulate the Posix unsetenv. */
2416 unsetenv (const char *name
)
2421 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2426 name_len
= strlen (name
);
2427 /* MS docs says an environment variable cannot be longer than 32K. */
2428 if (name_len
> 32767)
2433 /* It is safe to use 'alloca' with 32K size, since the stack is at
2434 least 2MB, and we set it to 8MB in the link command line. */
2435 var
= alloca (name_len
+ 2);
2436 strncpy (var
, name
, name_len
);
2437 var
[name_len
++] = '=';
2438 var
[name_len
] = '\0';
2439 return _putenv (var
);
2442 /* MS _putenv doesn't support removing a variable when the argument
2443 does not include the '=' character, so we fix that here. */
2445 sys_putenv (char *str
)
2447 const char *const name_end
= strchr (str
, '=');
2449 if (name_end
== NULL
)
2451 /* Remove the variable from the environment. */
2452 return unsetenv (str
);
2455 return _putenv (str
);
2458 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2461 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2464 HKEY hrootkey
= NULL
;
2467 /* Check both the current user and the local machine to see if
2468 we have any resources. */
2470 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2474 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2475 && (lpvalue
= xmalloc (cbData
)) != NULL
2476 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2478 RegCloseKey (hrootkey
);
2484 RegCloseKey (hrootkey
);
2487 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2491 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2492 && (lpvalue
= xmalloc (cbData
)) != NULL
2493 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2495 RegCloseKey (hrootkey
);
2501 RegCloseKey (hrootkey
);
2507 /* The argv[] array holds ANSI-encoded strings, and so this function
2508 works with ANS_encoded strings. */
2510 init_environment (char ** argv
)
2512 static const char * const tempdirs
[] = {
2513 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2518 const int imax
= ARRAYELTS (tempdirs
);
2520 /* Implementation note: This function explicitly works with ANSI
2521 file names, not with UTF-8 encoded file names. This is because
2522 this function pushes variables into the Emacs's environment, and
2523 the environment variables are always assumed to be in the
2524 locale-specific encoding. Do NOT call any functions that accept
2525 UTF-8 file names from this function! */
2527 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2528 temporary files and assume "/tmp" if $TMPDIR is unset, which
2529 will break on DOS/Windows. Refuse to work if we cannot find
2530 a directory, not even "c:/", usable for that purpose. */
2531 for (i
= 0; i
< imax
; i
++)
2533 const char *tmp
= tempdirs
[i
];
2536 tmp
= getenv (tmp
+ 1);
2537 /* Note that `access' can lie to us if the directory resides on a
2538 read-only filesystem, like CD-ROM or a write-protected floppy.
2539 The only way to be really sure is to actually create a file and
2540 see if it succeeds. But I think that's too much to ask. */
2542 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2543 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2545 char * var
= alloca (strlen (tmp
) + 8);
2546 sprintf (var
, "TMPDIR=%s", tmp
);
2547 _putenv (strdup (var
));
2554 Fcons (build_string ("no usable temporary directories found!!"),
2556 "While setting TMPDIR: ");
2558 /* Check for environment variables and use registry settings if they
2559 don't exist. Fallback on default values where applicable. */
2564 char locale_name
[32];
2565 char default_home
[MAX_PATH
];
2568 static const struct env_entry
2574 /* If the default value is NULL, we will use the value from the
2575 outside environment or the Registry, but will not push the
2576 variable into the Emacs environment if it is defined neither
2577 in the Registry nor in the outside environment. */
2579 {"PRELOAD_WINSOCK", NULL
},
2580 {"emacs_dir", "C:/emacs"},
2581 {"EMACSLOADPATH", NULL
},
2582 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2583 {"EMACSDATA", NULL
},
2584 {"EMACSPATH", NULL
},
2591 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2593 /* We need to copy dflt_envvars[] and work on the copy because we
2594 don't want the dumped Emacs to inherit the values of
2595 environment variables we saw during dumping (which could be on
2596 a different system). The defaults above must be left intact. */
2597 struct env_entry env_vars
[N_ENV_VARS
];
2599 for (i
= 0; i
< N_ENV_VARS
; i
++)
2600 env_vars
[i
] = dflt_envvars
[i
];
2602 /* For backwards compatibility, check if a .emacs file exists in C:/
2603 If not, then we can try to default to the appdata directory under the
2604 user's profile, which is more likely to be writable. */
2605 if (sys_access ("C:/.emacs", F_OK
) != 0)
2607 HRESULT profile_result
;
2608 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2609 of Windows 95 and NT4 that have not been updated to include
2611 ShGetFolderPath_fn get_folder_path
;
2612 get_folder_path
= (ShGetFolderPath_fn
)
2613 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2615 if (get_folder_path
!= NULL
)
2617 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2620 /* If we can't get the appdata dir, revert to old behavior. */
2621 if (profile_result
== S_OK
)
2623 env_vars
[0].def_value
= default_home
;
2629 /* Get default locale info and use it for LANG. */
2630 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2631 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2632 locale_name
, sizeof (locale_name
)))
2634 for (i
= 0; i
< N_ENV_VARS
; i
++)
2636 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2638 env_vars
[i
].def_value
= locale_name
;
2644 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2646 /* Treat emacs_dir specially: set it unconditionally based on our
2650 char modname
[MAX_PATH
];
2652 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2654 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2658 if ((p
= _mbsrchr (modname
, '\\'))
2659 /* From bin means installed Emacs, from src means uninstalled. */
2660 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2662 char buf
[SET_ENV_BUF_SIZE
];
2663 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2666 for (p
= modname
; *p
; p
= CharNext (p
))
2667 if (*p
== '\\') *p
= '/';
2669 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2670 _putenv (strdup (buf
));
2671 /* If we are running from the Posix-like build tree, define
2672 SHELL to point to our own cmdproxy. The loop below will
2673 then disregard PATH_EXEC and the default value. */
2674 if (within_build_tree
)
2676 _snprintf (buf
, sizeof (buf
) - 1,
2677 "SHELL=%s/nt/cmdproxy.exe", modname
);
2678 _putenv (strdup (buf
));
2683 for (i
= 0; i
< N_ENV_VARS
; i
++)
2685 if (!getenv (env_vars
[i
].name
))
2688 char bufc
[SET_ENV_BUF_SIZE
];
2690 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2691 /* Also ignore empty environment variables. */
2696 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2698 /* Look for cmdproxy.exe in every directory in
2699 PATH_EXEC. FIXME: This does not find cmdproxy
2700 in nt/ when we run uninstalled. */
2701 char fname
[MAX_PATH
];
2702 const char *pstart
= PATH_EXEC
, *pend
;
2705 pend
= _mbschr (pstart
, ';');
2707 pend
= pstart
+ strlen (pstart
);
2708 /* Be defensive against series of ;;; characters. */
2711 strncpy (fname
, pstart
, pend
- pstart
);
2712 fname
[pend
- pstart
] = '/';
2713 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2714 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2716 if (sys_access (bufc
, F_OK
) == 0)
2729 /* If not found in any directory, use the
2730 default as the last resort. */
2731 lpval
= env_vars
[i
].def_value
;
2732 dwType
= REG_EXPAND_SZ
;
2738 lpval
= env_vars
[i
].def_value
;
2739 dwType
= REG_EXPAND_SZ
;
2741 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2742 Vdelayed_warnings_list
2743 = Fcons (listn (CONSTYPE_HEAP
, 2,
2744 intern ("initialization"),
2745 build_string ("Setting HOME to C:\\ by default is deprecated")),
2746 Vdelayed_warnings_list
);
2751 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2753 if (dwType
== REG_EXPAND_SZ
)
2754 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2755 else if (dwType
== REG_SZ
)
2756 strcpy (buf1
, lpval
);
2757 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2759 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2761 _putenv (strdup (buf2
));
2771 /* Rebuild system configuration to reflect invoking system. */
2772 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2774 /* Another special case: on NT, the PATH variable is actually named
2775 "Path" although cmd.exe (perhaps NT itself) arranges for
2776 environment variable lookup and setting to be case insensitive.
2777 However, Emacs assumes a fully case sensitive environment, so we
2778 need to change "Path" to "PATH" to match the expectations of
2779 various elisp packages. We do this by the sneaky method of
2780 modifying the string in the C runtime environ entry.
2782 The same applies to COMSPEC. */
2786 for (envp
= environ
; *envp
; envp
++)
2787 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2788 memcpy (*envp
, "PATH=", 5);
2789 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2790 memcpy (*envp
, "COMSPEC=", 8);
2793 /* Remember the initial working directory for getcwd. */
2794 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2795 Does it matter anywhere in Emacs? */
2796 if (w32_unicode_filenames
)
2798 wchar_t wstartup_dir
[MAX_PATH
];
2800 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2802 filename_from_utf16 (wstartup_dir
, startup_dir
);
2806 char astartup_dir
[MAX_PATH
];
2808 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2810 filename_from_ansi (astartup_dir
, startup_dir
);
2814 static char modname
[MAX_PATH
];
2816 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2821 /* Determine if there is a middle mouse button, to allow parse_button
2822 to decide whether right mouse events should be mouse-2 or
2824 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2829 /* Called from expand-file-name when default-directory is not a string. */
2832 emacs_root_dir (void)
2834 static char root_dir
[MAX_UTF8_PATH
];
2837 p
= getenv ("emacs_dir");
2840 filename_from_ansi (p
, root_dir
);
2841 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2842 dostounix_filename (root_dir
);
2846 #include <sys/timeb.h>
2848 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2850 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2855 tv
->tv_sec
= tb
.time
;
2856 tv
->tv_usec
= tb
.millitm
* 1000L;
2857 /* Implementation note: _ftime sometimes doesn't update the dstflag
2858 according to the new timezone when the system timezone is
2859 changed. We could fix that by using GetSystemTime and
2860 GetTimeZoneInformation, but that doesn't seem necessary, since
2861 Emacs always calls gettimeofday with the 2nd argument NULL (see
2862 current_emacs_time). */
2865 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2866 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2871 /* Emulate fdutimens. */
2873 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2874 TIMESPEC[0] and TIMESPEC[1], respectively.
2875 FD must be either negative -- in which case it is ignored --
2876 or a file descriptor that is open on FILE.
2877 If FD is nonnegative, then FILE can be NULL, which means
2878 use just futimes instead of utimes.
2879 If TIMESPEC is null, FAIL.
2880 Return 0 on success, -1 (setting errno) on failure. */
2883 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2890 if (fd
< 0 && !file
)
2895 /* _futime's prototype defines 2nd arg as having the type 'struct
2896 _utimbuf', while utime needs to accept 'struct utimbuf' for
2897 compatibility with Posix. So we need to use 2 different (but
2898 equivalent) types to avoid compiler warnings, sigh. */
2901 struct _utimbuf _ut
;
2903 _ut
.actime
= timespec
[0].tv_sec
;
2904 _ut
.modtime
= timespec
[1].tv_sec
;
2905 return _futime (fd
, &_ut
);
2911 ut
.actime
= timespec
[0].tv_sec
;
2912 ut
.modtime
= timespec
[1].tv_sec
;
2913 /* Call 'utime', which is implemented below, not the MS library
2914 function, which fails on directories. */
2915 return utime (file
, &ut
);
2920 /* ------------------------------------------------------------------------- */
2921 /* IO support and wrapper functions for the Windows API. */
2922 /* ------------------------------------------------------------------------- */
2924 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2925 on network directories, so we handle that case here.
2926 (Ulrich Leodolter, 1/11/95). */
2928 sys_ctime (const time_t *t
)
2930 char *str
= (char *) ctime (t
);
2931 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2934 /* Emulate sleep...we could have done this with a define, but that
2935 would necessitate including windows.h in the files that used it.
2936 This is much easier. */
2938 sys_sleep (int seconds
)
2940 Sleep (seconds
* 1000);
2943 /* Internal MSVC functions for low-level descriptor munging */
2944 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2945 extern int __cdecl
_free_osfhnd (int fd
);
2947 /* parallel array of private info on file handles */
2948 filedesc fd_info
[ MAXDESC
];
2950 typedef struct volume_info_data
{
2951 struct volume_info_data
* next
;
2953 /* time when info was obtained */
2956 /* actual volume info */
2965 /* Global referenced by various functions. */
2966 static volume_info_data volume_info
;
2968 /* Vector to indicate which drives are local and fixed (for which cached
2969 data never expires). */
2970 static BOOL fixed_drives
[26];
2972 /* Consider cached volume information to be stale if older than 10s,
2973 at least for non-local drives. Info for fixed drives is never stale. */
2974 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2975 #define VOLINFO_STILL_VALID( root_dir, info ) \
2976 ( ( isalpha (root_dir[0]) && \
2977 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2978 || GetTickCount () - info->timestamp < 10000 )
2980 /* Cache support functions. */
2982 /* Simple linked list with linear search is sufficient. */
2983 static volume_info_data
*volume_cache
= NULL
;
2985 static volume_info_data
*
2986 lookup_volume_info (char * root_dir
)
2988 volume_info_data
* info
;
2990 for (info
= volume_cache
; info
; info
= info
->next
)
2991 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2997 add_volume_info (char * root_dir
, volume_info_data
* info
)
2999 info
->root_dir
= xstrdup (root_dir
);
3000 unixtodos_filename (info
->root_dir
);
3001 info
->next
= volume_cache
;
3002 volume_cache
= info
;
3006 /* Wrapper for GetVolumeInformation, which uses caching to avoid
3007 performance penalty (~2ms on 486 for local drives, 7.5ms for local
3008 cdrom drive, ~5-10ms or more for remote drives on LAN). */
3009 static volume_info_data
*
3010 GetCachedVolumeInformation (char * root_dir
)
3012 volume_info_data
* info
;
3013 char default_root
[ MAX_UTF8_PATH
];
3014 char name
[MAX_PATH
+1];
3015 char type
[MAX_PATH
+1];
3017 /* NULL for root_dir means use root from current directory. */
3018 if (root_dir
== NULL
)
3020 if (w32_unicode_filenames
)
3022 wchar_t curdirw
[MAX_PATH
];
3024 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
3026 filename_from_utf16 (curdirw
, default_root
);
3030 char curdira
[MAX_PATH
];
3032 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
3034 filename_from_ansi (curdira
, default_root
);
3036 parse_root (default_root
, (const char **)&root_dir
);
3038 root_dir
= default_root
;
3041 /* Local fixed drives can be cached permanently. Removable drives
3042 cannot be cached permanently, since the volume name and serial
3043 number (if nothing else) can change. Remote drives should be
3044 treated as if they are removable, since there is no sure way to
3045 tell whether they are or not. Also, the UNC association of drive
3046 letters mapped to remote volumes can be changed at any time (even
3047 by other processes) without notice.
3049 As a compromise, so we can benefit from caching info for remote
3050 volumes, we use a simple expiry mechanism to invalidate cache
3051 entries that are more than ten seconds old. */
3054 /* No point doing this, because WNetGetConnection is even slower than
3055 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
3056 GetDriveType is about the only call of this type which does not
3057 involve network access, and so is extremely quick). */
3059 /* Map drive letter to UNC if remote. */
3060 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
3062 char remote_name
[ 256 ];
3063 char drive
[3] = { root_dir
[0], ':' };
3065 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
3067 /* do something */ ;
3071 info
= lookup_volume_info (root_dir
);
3073 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
3079 /* Info is not cached, or is stale. */
3080 if (w32_unicode_filenames
)
3082 wchar_t root_w
[MAX_PATH
];
3083 wchar_t name_w
[MAX_PATH
+1];
3084 wchar_t type_w
[MAX_PATH
+1];
3086 filename_to_utf16 (root_dir
, root_w
);
3087 if (!GetVolumeInformationW (root_w
,
3088 name_w
, sizeof (name_w
),
3092 type_w
, sizeof (type_w
)))
3094 /* Hmm... not really 100% correct, as these 2 are not file
3096 filename_from_utf16 (name_w
, name
);
3097 filename_from_utf16 (type_w
, type
);
3101 char root_a
[MAX_PATH
];
3102 char name_a
[MAX_PATH
+1];
3103 char type_a
[MAX_PATH
+1];
3105 filename_to_ansi (root_dir
, root_a
);
3106 if (!GetVolumeInformationA (root_a
,
3107 name_a
, sizeof (name_a
),
3111 type_a
, sizeof (type_a
)))
3113 filename_from_ansi (name_a
, name
);
3114 filename_from_ansi (type_a
, type
);
3117 /* Cache the volume information for future use, overwriting existing
3118 entry if present. */
3121 info
= xmalloc (sizeof (volume_info_data
));
3122 add_volume_info (root_dir
, info
);
3130 info
->name
= xstrdup (name
);
3131 unixtodos_filename (info
->name
);
3132 info
->serialnum
= serialnum
;
3133 info
->maxcomp
= maxcomp
;
3134 info
->flags
= flags
;
3135 info
->type
= xstrdup (type
);
3136 info
->timestamp
= GetTickCount ();
3142 /* Get information on the volume where NAME is held; set path pointer to
3143 start of pathname in NAME (past UNC header\volume header if present),
3144 if pPath is non-NULL.
3146 Note: if NAME includes symlinks, the information is for the volume
3147 of the symlink, not of its target. That's because, even though
3148 GetVolumeInformation returns information about the symlink target
3149 of its argument, we only pass the root directory to
3150 GetVolumeInformation, not the full NAME. */
3152 get_volume_info (const char * name
, const char ** pPath
)
3154 char temp
[MAX_UTF8_PATH
];
3155 char *rootname
= NULL
; /* default to current volume */
3156 volume_info_data
* info
;
3157 int root_len
= parse_root (name
, pPath
);
3162 /* Copy the root name of the volume, if given. */
3165 strncpy (temp
, name
, root_len
);
3166 temp
[root_len
] = '\0';
3167 unixtodos_filename (temp
);
3171 info
= GetCachedVolumeInformation (rootname
);
3174 /* Set global referenced by other functions. */
3175 volume_info
= *info
;
3181 /* Determine if volume is FAT format (ie. only supports short 8.3
3182 names); also set path pointer to start of pathname in name, if
3183 pPath is non-NULL. */
3185 is_fat_volume (const char * name
, const char ** pPath
)
3187 if (get_volume_info (name
, pPath
))
3188 return (volume_info
.maxcomp
== 12);
3192 /* Convert all slashes in a filename to backslashes, and map filename
3193 to a valid 8.3 name if necessary. The result is a pointer to a
3194 static buffer, so CAVEAT EMPTOR! */
3196 map_w32_filename (const char * name
, const char ** pPath
)
3198 static char shortname
[MAX_UTF8_PATH
];
3199 char * str
= shortname
;
3202 const char * save_name
= name
;
3204 if (strlen (name
) >= sizeof (shortname
))
3206 /* Return a filename which will cause callers to fail. */
3207 strcpy (shortname
, "?");
3211 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3213 register int left
= 8; /* maximum number of chars in part */
3214 register int extn
= 0; /* extension added? */
3215 register int dots
= 2; /* maximum number of dots allowed */
3218 *str
++ = *name
++; /* skip past UNC header */
3220 while ((c
= *name
++))
3227 *str
++ = (c
== ':' ? ':' : '\\');
3228 extn
= 0; /* reset extension flags */
3229 dots
= 2; /* max 2 dots */
3230 left
= 8; /* max length 8 for main part */
3235 /* Convert path components of the form .xxx to _xxx,
3236 but leave . and .. as they are. This allows .emacs
3237 to be read as _emacs, for example. */
3241 IS_DIRECTORY_SEP (*name
))
3256 extn
= 1; /* we've got an extension */
3257 left
= 3; /* 3 chars in extension */
3261 /* any embedded dots after the first are converted to _ */
3266 case '#': /* don't lose these, they're important */
3268 str
[-1] = c
; /* replace last character of part */
3271 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3273 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3275 dots
= 0; /* started a path component */
3284 strcpy (shortname
, name
);
3285 unixtodos_filename (shortname
);
3289 *pPath
= shortname
+ (path
- save_name
);
3295 is_exec (const char * name
)
3297 char * p
= strrchr (name
, '.');
3300 && (xstrcasecmp (p
, ".exe") == 0 ||
3301 xstrcasecmp (p
, ".com") == 0 ||
3302 xstrcasecmp (p
, ".bat") == 0 ||
3303 xstrcasecmp (p
, ".cmd") == 0));
3306 /* Emulate the Unix directory procedures opendir, closedir, and
3307 readdir. We rename them to sys_* names because some versions of
3308 MinGW startup code call opendir and readdir to glob wildcards, and
3309 the code that calls them doesn't grok UTF-8 encoded file names we
3310 produce in dirent->d_name[]. */
3312 struct dirent dir_static
; /* simulated directory contents */
3313 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3314 static int dir_is_fat
;
3315 static char dir_pathname
[MAX_UTF8_PATH
];
3316 static WIN32_FIND_DATAW dir_find_data_w
;
3317 static WIN32_FIND_DATAA dir_find_data_a
;
3318 #define DIR_FIND_DATA_W 1
3319 #define DIR_FIND_DATA_A 2
3320 static int last_dir_find_data
= -1;
3322 /* Support shares on a network resource as subdirectories of a read-only
3324 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3325 static HANDLE
open_unc_volume (const char *);
3326 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3327 static void close_unc_volume (HANDLE
);
3330 sys_opendir (const char *filename
)
3334 /* Opening is done by FindFirstFile. However, a read is inherent to
3335 this operation, so we defer the open until read time. */
3337 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3339 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3342 /* Note: We don't support traversal of UNC volumes via symlinks.
3343 Doing so would mean punishing 99.99% of use cases by resolving
3344 all the possible symlinks in FILENAME, recursively. */
3345 if (is_unc_volume (filename
))
3347 wnet_enum_handle
= open_unc_volume (filename
);
3348 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3352 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3359 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3360 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3361 /* Note: We don't support symlinks to file names on FAT volumes.
3362 Doing so would mean punishing 99.99% of use cases by resolving
3363 all the possible symlinks in FILENAME, recursively. */
3364 dir_is_fat
= is_fat_volume (filename
, NULL
);
3370 sys_closedir (DIR *dirp
)
3372 /* If we have a find-handle open, close it. */
3373 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3375 FindClose (dir_find_handle
);
3376 dir_find_handle
= INVALID_HANDLE_VALUE
;
3378 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3380 close_unc_volume (wnet_enum_handle
);
3381 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3383 xfree ((char *) dirp
);
3387 sys_readdir (DIR *dirp
)
3389 int downcase
= !NILP (Vw32_downcase_file_names
);
3391 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3393 if (!read_unc_volume (wnet_enum_handle
,
3394 dir_find_data_w
.cFileName
,
3395 dir_find_data_a
.cFileName
,
3399 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3400 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3402 char filename
[MAX_UTF8_PATH
+ 2];
3405 strcpy (filename
, dir_pathname
);
3406 ln
= strlen (filename
);
3407 if (!IS_DIRECTORY_SEP (filename
[ln
- 1]))
3408 filename
[ln
++] = '\\';
3409 strcpy (filename
+ ln
, "*");
3411 /* Note: No need to resolve symlinks in FILENAME, because
3412 FindFirst opens the directory that is the target of a
3414 if (w32_unicode_filenames
)
3416 wchar_t fnw
[MAX_PATH
];
3418 filename_to_utf16 (filename
, fnw
);
3419 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3425 filename_to_ansi (filename
, fna
);
3426 /* If FILENAME is not representable by the current ANSI
3427 codepage, we don't want FindFirstFileA to interpret the
3428 '?' characters as a wildcard. */
3429 if (_mbspbrk (fna
, "?"))
3430 dir_find_handle
= INVALID_HANDLE_VALUE
;
3432 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3435 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3437 switch (GetLastError ())
3439 case ERROR_PATH_NOT_FOUND
:
3440 case ERROR_ACCESS_DENIED
:
3441 case ERROR_INVALID_DRIVE
:
3442 case ERROR_BAD_NETPATH
:
3443 /* This special value will be noticed by
3444 directory_files_internal, which see. */
3453 else if (w32_unicode_filenames
)
3455 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3460 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3464 /* Emacs never uses this value, so don't bother making it match
3465 value returned by stat(). */
3466 dir_static
.d_ino
= 1;
3468 if (w32_unicode_filenames
)
3470 if (downcase
|| dir_is_fat
)
3472 wchar_t tem
[MAX_PATH
];
3474 wcscpy (tem
, dir_find_data_w
.cFileName
);
3476 filename_from_utf16 (tem
, dir_static
.d_name
);
3479 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3480 last_dir_find_data
= DIR_FIND_DATA_W
;
3486 /* If the file name in cFileName[] includes `?' characters, it
3487 means the original file name used characters that cannot be
3488 represented by the current ANSI codepage. To avoid total
3489 lossage, retrieve the short 8+3 alias of the long file
3491 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3493 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3494 /* 8+3 aliases are returned in all caps, which could break
3495 various alists that look at filenames' extensions. */
3498 else if (downcase
|| dir_is_fat
)
3499 strcpy (tem
, dir_find_data_a
.cFileName
);
3501 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3502 if (downcase
|| dir_is_fat
)
3505 filename_from_ansi (tem
, dir_static
.d_name
);
3507 last_dir_find_data
= DIR_FIND_DATA_A
;
3510 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3511 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3512 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3518 open_unc_volume (const char *path
)
3520 const char *fn
= map_w32_filename (path
, NULL
);
3524 if (w32_unicode_filenames
)
3527 wchar_t fnw
[MAX_PATH
];
3529 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3530 nrw
.dwType
= RESOURCETYPE_DISK
;
3531 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3532 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3533 nrw
.lpLocalName
= NULL
;
3534 filename_to_utf16 (fn
, fnw
);
3535 nrw
.lpRemoteName
= fnw
;
3536 nrw
.lpComment
= NULL
;
3537 nrw
.lpProvider
= NULL
;
3539 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3540 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3547 nra
.dwScope
= RESOURCE_GLOBALNET
;
3548 nra
.dwType
= RESOURCETYPE_DISK
;
3549 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3550 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3551 nra
.lpLocalName
= NULL
;
3552 filename_to_ansi (fn
, fna
);
3553 nra
.lpRemoteName
= fna
;
3554 nra
.lpComment
= NULL
;
3555 nra
.lpProvider
= NULL
;
3557 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3558 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3560 if (result
== NO_ERROR
)
3563 return INVALID_HANDLE_VALUE
;
3567 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3572 DWORD bufsize
= 512;
3576 if (w32_unicode_filenames
)
3581 buffer
= alloca (bufsize
);
3582 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3583 if (result
!= NO_ERROR
)
3585 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3586 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3588 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3590 wcsncpy (fname_w
, ptrw
, size
);
3595 int dbcs_p
= max_filename_mbslen () > 1;
3598 buffer
= alloca (bufsize
);
3599 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3600 if (result
!= NO_ERROR
)
3602 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3605 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3608 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3609 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3612 strncpy (fname_a
, ptra
, size
);
3620 close_unc_volume (HANDLE henum
)
3622 if (henum
!= INVALID_HANDLE_VALUE
)
3623 WNetCloseEnum (henum
);
3627 unc_volume_file_attributes (const char *path
)
3632 henum
= open_unc_volume (path
);
3633 if (henum
== INVALID_HANDLE_VALUE
)
3636 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3638 close_unc_volume (henum
);
3643 /* Ensure a network connection is authenticated. */
3645 logon_network_drive (const char *path
)
3647 char share
[MAX_UTF8_PATH
];
3654 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3655 drvtype
= DRIVE_REMOTE
;
3656 else if (path
[0] == '\0' || path
[1] != ':')
3657 drvtype
= GetDriveType (NULL
);
3664 drvtype
= GetDriveType (drive
);
3667 /* Only logon to networked drives. */
3668 if (drvtype
!= DRIVE_REMOTE
)
3672 strncpy (share
, path
, MAX_UTF8_PATH
);
3673 /* Truncate to just server and share name. */
3674 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3676 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3683 if (w32_unicode_filenames
)
3685 NETRESOURCEW resourcew
;
3686 wchar_t share_w
[MAX_PATH
];
3688 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3689 resourcew
.dwType
= RESOURCETYPE_DISK
;
3690 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3691 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3692 resourcew
.lpLocalName
= NULL
;
3693 filename_to_utf16 (share
, share_w
);
3694 resourcew
.lpRemoteName
= share_w
;
3695 resourcew
.lpProvider
= NULL
;
3697 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3701 NETRESOURCEA resourcea
;
3702 char share_a
[MAX_PATH
];
3704 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3705 resourcea
.dwType
= RESOURCETYPE_DISK
;
3706 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3707 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3708 resourcea
.lpLocalName
= NULL
;
3709 filename_to_ansi (share
, share_a
);
3710 resourcea
.lpRemoteName
= share_a
;
3711 resourcea
.lpProvider
= NULL
;
3713 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3719 case ERROR_ALREADY_ASSIGNED
:
3721 case ERROR_ACCESS_DENIED
:
3722 case ERROR_LOGON_FAILURE
:
3728 case ERROR_BAD_NET_NAME
:
3729 case ERROR_NO_NET_OR_BAD_PATH
:
3730 case ERROR_NO_NETWORK
:
3731 case ERROR_CANCELLED
:
3738 /* Emulate faccessat(2). */
3740 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3744 if (dirfd
!= AT_FDCWD
3745 && !(IS_DIRECTORY_SEP (path
[0])
3746 || IS_DEVICE_SEP (path
[1])))
3752 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3753 newer versions blow up when passed D_OK. */
3754 path
= map_w32_filename (path
, NULL
);
3755 /* If the last element of PATH is a symlink, we need to resolve it
3756 to get the attributes of its target file. Note: any symlinks in
3757 PATH elements other than the last one are transparently resolved
3758 by GetFileAttributes below. */
3759 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3760 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3761 path
= chase_symlinks (path
);
3763 if (w32_unicode_filenames
)
3765 wchar_t path_w
[MAX_PATH
];
3767 filename_to_utf16 (path
, path_w
);
3768 attributes
= GetFileAttributesW (path_w
);
3772 char path_a
[MAX_PATH
];
3774 filename_to_ansi (path
, path_a
);
3775 attributes
= GetFileAttributesA (path_a
);
3778 if (attributes
== -1)
3780 DWORD w32err
= GetLastError ();
3784 case ERROR_INVALID_NAME
:
3785 case ERROR_BAD_PATHNAME
:
3786 if (is_unc_volume (path
))
3788 attributes
= unc_volume_file_attributes (path
);
3789 if (attributes
== -1)
3797 case ERROR_FILE_NOT_FOUND
:
3798 case ERROR_BAD_NETPATH
:
3807 if ((mode
& X_OK
) != 0
3808 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3813 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3818 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3826 /* A version of 'access' to be used locally with file names in
3827 locale-specific encoding. Does not resolve symlinks and does not
3828 support file names on FAT12 and FAT16 volumes, but that's OK, since
3829 we only invoke this function for files inside the Emacs source or
3830 installation tree, on directories (so any symlinks should have the
3831 directory bit set), and on short file names such as "C:/.emacs". */
3833 sys_access (const char *fname
, int mode
)
3835 char fname_copy
[MAX_PATH
], *p
;
3838 strcpy (fname_copy
, fname
);
3839 /* Do the equivalent of unixtodos_filename. */
3840 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3844 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3846 DWORD w32err
= GetLastError ();
3850 case ERROR_INVALID_NAME
:
3851 case ERROR_BAD_PATHNAME
:
3852 case ERROR_FILE_NOT_FOUND
:
3853 case ERROR_BAD_NETPATH
:
3862 if ((mode
& X_OK
) != 0
3863 && !(is_exec (fname_copy
)
3864 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3869 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3874 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3882 /* Shadow some MSVC runtime functions to map requests for long filenames
3883 to reasonable short names if necessary. This was originally added to
3884 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3888 sys_chdir (const char * path
)
3890 path
= map_w32_filename (path
, NULL
);
3891 if (w32_unicode_filenames
)
3893 wchar_t newdir_w
[MAX_PATH
];
3895 if (filename_to_utf16 (path
, newdir_w
) == 0)
3896 return _wchdir (newdir_w
);
3901 char newdir_a
[MAX_PATH
];
3903 if (filename_to_ansi (path
, newdir_a
) == 0)
3904 return _chdir (newdir_a
);
3910 sys_chmod (const char * path
, int mode
)
3912 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3913 if (w32_unicode_filenames
)
3915 wchar_t path_w
[MAX_PATH
];
3917 filename_to_utf16 (path
, path_w
);
3918 return _wchmod (path_w
, mode
);
3922 char path_a
[MAX_PATH
];
3924 filename_to_ansi (path
, path_a
);
3925 return _chmod (path_a
, mode
);
3930 sys_creat (const char * path
, int mode
)
3932 path
= map_w32_filename (path
, NULL
);
3933 if (w32_unicode_filenames
)
3935 wchar_t path_w
[MAX_PATH
];
3937 filename_to_utf16 (path
, path_w
);
3938 return _wcreat (path_w
, mode
);
3942 char path_a
[MAX_PATH
];
3944 filename_to_ansi (path
, path_a
);
3945 return _creat (path_a
, mode
);
3950 sys_fopen (const char * path
, const char * mode
)
3954 const char * mode_save
= mode
;
3956 /* Force all file handles to be non-inheritable. This is necessary to
3957 ensure child processes don't unwittingly inherit handles that might
3958 prevent future file access. */
3962 else if (mode
[0] == 'w' || mode
[0] == 'a')
3963 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3967 /* Only do simplistic option parsing. */
3971 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3974 else if (mode
[0] == 'b')
3979 else if (mode
[0] == 't')
3986 path
= map_w32_filename (path
, NULL
);
3987 if (w32_unicode_filenames
)
3989 wchar_t path_w
[MAX_PATH
];
3991 filename_to_utf16 (path
, path_w
);
3992 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3996 char path_a
[MAX_PATH
];
3998 filename_to_ansi (path
, path_a
);
3999 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
4004 return _fdopen (fd
, mode_save
);
4007 /* This only works on NTFS volumes, but is useful to have. */
4009 sys_link (const char * old
, const char * new)
4013 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
4014 wchar_t oldname_w
[MAX_PATH
];
4015 char oldname_a
[MAX_PATH
];
4017 if (old
== NULL
|| new == NULL
)
4023 strcpy (oldname
, map_w32_filename (old
, NULL
));
4024 strcpy (newname
, map_w32_filename (new, NULL
));
4026 if (w32_unicode_filenames
)
4028 filename_to_utf16 (oldname
, oldname_w
);
4029 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4030 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4034 filename_to_ansi (oldname
, oldname_a
);
4035 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4036 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4038 if (fileh
!= INVALID_HANDLE_VALUE
)
4042 /* Confusingly, the "alternate" stream name field does not apply
4043 when restoring a hard link, and instead contains the actual
4044 stream data for the link (ie. the name of the link to create).
4045 The WIN32_STREAM_ID structure before the cStreamName field is
4046 the stream header, which is then immediately followed by the
4050 WIN32_STREAM_ID wid
;
4051 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4054 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4055 indicates that flag is unsupported for CP_UTF8, and OTOH says
4056 it is the default anyway. */
4057 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4058 data
.wid
.cStreamName
, MAX_PATH
);
4061 LPVOID context
= NULL
;
4064 data
.wid
.dwStreamId
= BACKUP_LINK
;
4065 data
.wid
.dwStreamAttributes
= 0;
4066 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4067 data
.wid
.Size
.HighPart
= 0;
4068 data
.wid
.dwStreamNameSize
= 0;
4070 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4071 offsetof (WIN32_STREAM_ID
, cStreamName
)
4072 + data
.wid
.Size
.LowPart
,
4073 &wbytes
, FALSE
, FALSE
, &context
)
4074 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4081 DWORD err
= GetLastError ();
4086 case ERROR_ACCESS_DENIED
:
4087 /* This is what happens when OLDNAME is a directory,
4088 since Windows doesn't support hard links to
4089 directories. Posix says to set errno to EPERM in
4091 if (w32_unicode_filenames
)
4092 attributes
= GetFileAttributesW (oldname_w
);
4094 attributes
= GetFileAttributesA (oldname_a
);
4095 if (attributes
!= -1
4096 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4098 else if (attributes
== -1
4099 && is_unc_volume (oldname
)
4100 && unc_volume_file_attributes (oldname
) != -1)
4105 case ERROR_TOO_MANY_LINKS
:
4108 case ERROR_NOT_SAME_DEVICE
:
4118 CloseHandle (fileh
);
4127 sys_mkdir (const char * path
)
4129 path
= map_w32_filename (path
, NULL
);
4131 if (w32_unicode_filenames
)
4133 wchar_t path_w
[MAX_PATH
];
4135 filename_to_utf16 (path
, path_w
);
4136 return _wmkdir (path_w
);
4140 char path_a
[MAX_PATH
];
4142 filename_to_ansi (path
, path_a
);
4143 return _mkdir (path_a
);
4148 sys_open (const char * path
, int oflag
, int mode
)
4150 const char* mpath
= map_w32_filename (path
, NULL
);
4153 if (w32_unicode_filenames
)
4155 wchar_t mpath_w
[MAX_PATH
];
4157 filename_to_utf16 (mpath
, mpath_w
);
4158 /* If possible, try to open file without _O_CREAT, to be able to
4159 write to existing hidden and system files. Force all file
4160 handles to be non-inheritable. */
4161 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4162 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4164 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4168 char mpath_a
[MAX_PATH
];
4170 filename_to_ansi (mpath
, mpath_a
);
4171 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4172 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4174 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4180 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4183 Standard algorithm for generating a temporary file name seems to be
4184 use pid or tid with a letter on the front (in place of the 6 X's)
4185 and cycle through the letters to find a unique name. We extend
4186 that to allow any reasonable character as the first of the 6 X's,
4187 so that the number of simultaneously used temporary files will be
4191 mkostemp (char * template, int flags
)
4195 unsigned uid
= GetCurrentThreadId ();
4196 int save_errno
= errno
;
4197 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4200 if (template == NULL
)
4203 p
= template + strlen (template);
4205 /* replace up to the last 5 X's with uid in decimal */
4206 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4208 p
[0] = '0' + uid
% 10;
4212 if (i
< 0 && p
[0] == 'X')
4217 p
[0] = first_char
[i
];
4218 if ((fd
= sys_open (template,
4219 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4220 S_IRUSR
| S_IWUSR
)) >= 0
4228 while (++i
< sizeof (first_char
));
4231 /* Template is badly formed or else we can't generate a unique name. */
4236 fchmod (int fd
, mode_t mode
)
4242 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4245 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4248 bool have_temp_a
= false;
4250 /* MoveFile on Windows 95 doesn't correctly change the short file name
4251 alias in a number of circumstances (it is not easy to predict when
4252 just by looking at oldname and newname, unfortunately). In these
4253 cases, renaming through a temporary name avoids the problem.
4255 A second problem on Windows 95 is that renaming through a temp name when
4256 newname is uppercase fails (the final long name ends up in
4257 lowercase, although the short alias might be uppercase) UNLESS the
4258 long temp name is not 8.3.
4260 So, on Windows 95 we always rename through a temp name, and we make sure
4261 the temp name has a long extension to ensure correct renaming. */
4263 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4265 /* volume_info is set indirectly by map_w32_filename. */
4266 oldname_dev
= volume_info
.serialnum
;
4268 if (os_subtype
== OS_9X
)
4273 char oldname_a
[MAX_PATH
];
4275 oldname
= map_w32_filename (oldname
, NULL
);
4276 filename_to_ansi (oldname
, oldname_a
);
4277 filename_to_ansi (temp
, temp_a
);
4278 if ((o
= strrchr (oldname_a
, '\\')))
4281 o
= (char *) oldname_a
;
4283 if ((p
= strrchr (temp_a
, '\\')))
4290 /* Force temp name to require a manufactured 8.3 alias - this
4291 seems to make the second rename work properly. */
4292 sprintf (p
, "_.%s.%u", o
, i
);
4294 result
= rename (oldname_a
, temp_a
);
4296 /* This loop must surely terminate! */
4297 while (result
< 0 && errno
== EEXIST
);
4303 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4304 (at least if it is a file; don't do this for directories).
4306 Since we mustn't do this if we are just changing the case of the
4307 file name (we would end up deleting the file we are trying to
4308 rename!), we let rename detect if the destination file already
4309 exists - that way we avoid the possible pitfalls of trying to
4310 determine ourselves whether two names really refer to the same
4311 file, which is not always possible in the general case. (Consider
4312 all the permutations of shared or subst'd drives, etc.) */
4314 newname
= map_w32_filename (newname
, NULL
);
4316 /* volume_info is set indirectly by map_w32_filename. */
4317 newname_dev
= volume_info
.serialnum
;
4319 if (w32_unicode_filenames
)
4321 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4323 filename_to_utf16 (temp
, temp_w
);
4324 filename_to_utf16 (newname
, newname_w
);
4325 result
= _wrename (temp_w
, newname_w
);
4326 if (result
< 0 && force
)
4328 DWORD w32err
= GetLastError ();
4331 && newname_dev
!= oldname_dev
)
4333 /* The implementation of `rename' on Windows does not return
4334 errno = EXDEV when you are moving a directory to a
4335 different storage device (ex. logical disk). It returns
4336 EACCES instead. So here we handle such situations and
4340 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4341 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4344 else if (errno
== EEXIST
)
4346 if (_wchmod (newname_w
, 0666) != 0)
4348 if (_wunlink (newname_w
) != 0)
4350 result
= _wrename (temp_w
, newname_w
);
4352 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4353 && is_symlink (temp
))
4355 /* This is Windows prohibiting the user from creating a
4356 symlink in another place, since that requires
4364 char newname_a
[MAX_PATH
];
4367 filename_to_ansi (temp
, temp_a
);
4368 filename_to_ansi (newname
, newname_a
);
4369 result
= rename (temp_a
, newname_a
);
4370 if (result
< 0 && force
)
4372 DWORD w32err
= GetLastError ();
4375 && newname_dev
!= oldname_dev
)
4379 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4380 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4383 else if (errno
== EEXIST
)
4385 if (_chmod (newname_a
, 0666) != 0)
4387 if (_unlink (newname_a
) != 0)
4389 result
= rename (temp_a
, newname_a
);
4391 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4392 && is_symlink (temp
))
4401 sys_rename (char const *old
, char const *new)
4403 return sys_rename_replace (old
, new, TRUE
);
4407 sys_rmdir (const char * path
)
4409 path
= map_w32_filename (path
, NULL
);
4411 if (w32_unicode_filenames
)
4413 wchar_t path_w
[MAX_PATH
];
4415 filename_to_utf16 (path
, path_w
);
4416 return _wrmdir (path_w
);
4420 char path_a
[MAX_PATH
];
4422 filename_to_ansi (path
, path_a
);
4423 return _rmdir (path_a
);
4428 sys_unlink (const char * path
)
4430 path
= map_w32_filename (path
, NULL
);
4432 if (w32_unicode_filenames
)
4434 wchar_t path_w
[MAX_PATH
];
4436 filename_to_utf16 (path
, path_w
);
4437 /* On Unix, unlink works without write permission. */
4438 _wchmod (path_w
, 0666);
4439 return _wunlink (path_w
);
4443 char path_a
[MAX_PATH
];
4445 filename_to_ansi (path
, path_a
);
4446 _chmod (path_a
, 0666);
4447 return _unlink (path_a
);
4451 static FILETIME utc_base_ft
;
4452 static ULONGLONG utc_base
; /* In 100ns units */
4453 static int init
= 0;
4455 #define FILETIME_TO_U64(result, ft) \
4457 ULARGE_INTEGER uiTemp; \
4458 uiTemp.LowPart = (ft).dwLowDateTime; \
4459 uiTemp.HighPart = (ft).dwHighDateTime; \
4460 result = uiTemp.QuadPart; \
4464 initialize_utc_base (void)
4466 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4475 st
.wMilliseconds
= 0;
4477 SystemTimeToFileTime (&st
, &utc_base_ft
);
4478 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4482 convert_time (FILETIME ft
)
4488 initialize_utc_base ();
4492 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4495 FILETIME_TO_U64 (tmp
, ft
);
4496 return (time_t) ((tmp
- utc_base
) / 10000000L);
4500 convert_from_time_t (time_t time
, FILETIME
* pft
)
4506 initialize_utc_base ();
4510 /* time in 100ns units since 1-Jan-1601 */
4511 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4512 pft
->dwHighDateTime
= tmp
.HighPart
;
4513 pft
->dwLowDateTime
= tmp
.LowPart
;
4516 static PSECURITY_DESCRIPTOR
4517 get_file_security_desc_by_handle (HANDLE h
)
4519 PSECURITY_DESCRIPTOR psd
= NULL
;
4521 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4522 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4524 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4525 NULL
, NULL
, NULL
, NULL
, &psd
);
4526 if (err
!= ERROR_SUCCESS
)
4532 static PSECURITY_DESCRIPTOR
4533 get_file_security_desc_by_name (const char *fname
)
4535 PSECURITY_DESCRIPTOR psd
= NULL
;
4537 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4538 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4540 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4542 err
= GetLastError ();
4543 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4547 psd
= xmalloc (sd_len
);
4548 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4560 unsigned n_subauthorities
;
4562 /* Use the last sub-authority value of the RID, the relative
4563 portion of the SID, as user/group ID. */
4564 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4565 if (n_subauthorities
< 1)
4566 return 0; /* the "World" RID */
4567 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4570 /* Caching SID and account values for faster lokup. */
4574 struct w32_id
*next
;
4576 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4579 static struct w32_id
*w32_idlist
;
4582 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4584 struct w32_id
*tail
, *found
;
4586 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4588 if (equal_sid ((PSID
)tail
->sid
, sid
))
4597 strcpy (name
, found
->name
);
4605 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4608 struct w32_id
*new_entry
;
4610 /* We don't want to leave behind stale cache from when Emacs was
4614 sid_len
= get_length_sid (sid
);
4615 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4618 new_entry
->rid
= id
;
4619 strcpy (new_entry
->name
, name
);
4620 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4621 new_entry
->next
= w32_idlist
;
4622 w32_idlist
= new_entry
;
4631 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4635 SID_NAME_USE ignore
;
4637 DWORD name_len
= sizeof (name
);
4639 DWORD domain_len
= sizeof (domain
);
4644 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4645 else if (what
== GID
)
4646 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4650 if (!result
|| !is_valid_sid (sid
))
4652 else if (!w32_cached_id (sid
, id
, nm
))
4654 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4655 domain
, &domain_len
, &ignore
)
4656 || name_len
> UNLEN
+1)
4660 *id
= get_rid (sid
);
4662 w32_add_to_cache (sid
, *id
, name
);
4669 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4671 int dflt_usr
= 0, dflt_grp
= 0;
4680 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4682 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4685 /* Consider files to belong to current user/group, if we cannot get
4686 more accurate information. */
4689 st
->st_uid
= dflt_passwd
.pw_uid
;
4690 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4694 st
->st_gid
= dflt_passwd
.pw_gid
;
4695 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4699 /* Return non-zero if NAME is a potentially slow filesystem. */
4701 is_slow_fs (const char *name
)
4706 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4707 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4708 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4709 devtype
= GetDriveType (NULL
); /* use root of current drive */
4712 /* GetDriveType needs the root directory of the drive. */
4713 strncpy (drive_root
, name
, 2);
4714 drive_root
[2] = '\\';
4715 drive_root
[3] = '\0';
4716 devtype
= GetDriveType (drive_root
);
4718 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4721 /* If this is non-zero, the caller wants accurate information about
4722 file's owner and group, which could be expensive to get. dired.c
4723 uses this flag when needed for the job at hand. */
4724 int w32_stat_get_owner_group
;
4726 /* MSVC stat function can't cope with UNC names and has other bugs, so
4727 replace it with our own. This also allows us to calculate consistent
4728 inode values and owner/group without hacks in the main Emacs code,
4729 and support file names encoded in UTF-8. */
4732 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4734 char *name
, *save_name
, *r
;
4735 WIN32_FIND_DATAW wfd_w
;
4736 WIN32_FIND_DATAA wfd_a
;
4738 unsigned __int64 fake_inode
= 0;
4741 int rootdir
= FALSE
;
4742 PSECURITY_DESCRIPTOR psd
= NULL
;
4743 int is_a_symlink
= 0;
4744 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4745 DWORD access_rights
= 0;
4746 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4747 FILETIME ctime
, atime
, wtime
;
4748 wchar_t name_w
[MAX_PATH
];
4749 char name_a
[MAX_PATH
];
4751 if (path
== NULL
|| buf
== NULL
)
4757 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4758 /* Must be valid filename, no wild cards or other invalid
4760 if (strpbrk (name
, "*?|<>\""))
4766 len
= strlen (name
);
4767 /* Allocate 1 extra byte so that we could append a slash to a root
4768 directory, down below. */
4769 name
= strcpy (alloca (len
+ 2), name
);
4771 /* Avoid a somewhat costly call to is_symlink if the filesystem
4772 doesn't support symlinks. */
4773 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4774 is_a_symlink
= is_symlink (name
);
4776 /* Plan A: Open the file and get all the necessary information via
4777 the resulting handle. This solves several issues in one blow:
4779 . retrieves attributes for the target of a symlink, if needed
4780 . gets attributes of root directories and symlinks pointing to
4781 root directories, thus avoiding the need for special-casing
4782 these and detecting them by examining the file-name format
4783 . retrieves more accurate attributes (e.g., non-zero size for
4784 some directories, esp. directories that are junction points)
4785 . correctly resolves "c:/..", "/.." and similar file names
4786 . avoids run-time penalties for 99% of use cases
4788 Plan A is always tried first, unless the user asked not to (but
4789 if the file is a symlink and we need to follow links, we try Plan
4790 A even if the user asked not to).
4792 If Plan A fails, we go to Plan B (below), where various
4793 potentially expensive techniques must be used to handle "special"
4794 files such as UNC volumes etc. */
4795 if (!(NILP (Vw32_get_true_file_attributes
)
4796 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4797 /* Following symlinks requires getting the info by handle. */
4798 || (is_a_symlink
&& follow_symlinks
))
4800 BY_HANDLE_FILE_INFORMATION info
;
4802 if (is_a_symlink
&& !follow_symlinks
)
4803 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4804 /* READ_CONTROL access rights are required to get security info
4805 by handle. But if the OS doesn't support security in the
4806 first place, we don't need to try. */
4807 if (is_windows_9x () != TRUE
)
4808 access_rights
|= READ_CONTROL
;
4810 if (w32_unicode_filenames
)
4812 filename_to_utf16 (name
, name_w
);
4813 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4815 /* If CreateFile fails with READ_CONTROL, try again with
4816 zero as access rights. */
4817 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4818 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4823 filename_to_ansi (name
, name_a
);
4824 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4826 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4827 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4830 if (fh
== INVALID_HANDLE_VALUE
)
4831 goto no_true_file_attributes
;
4833 /* This is more accurate in terms of getting the correct number
4834 of links, but is quite slow (it is noticeable when Emacs is
4835 making a list of file name completions). */
4836 if (GetFileInformationByHandle (fh
, &info
))
4838 nlinks
= info
.nNumberOfLinks
;
4839 /* Might as well use file index to fake inode values, but this
4840 is not guaranteed to be unique unless we keep a handle open
4841 all the time (even then there are situations where it is
4842 not unique). Reputedly, there are at most 48 bits of info
4843 (on NTFS, presumably less on FAT). */
4844 fake_inode
= info
.nFileIndexHigh
;
4846 fake_inode
+= info
.nFileIndexLow
;
4847 serialnum
= info
.dwVolumeSerialNumber
;
4848 fs_high
= info
.nFileSizeHigh
;
4849 fs_low
= info
.nFileSizeLow
;
4850 ctime
= info
.ftCreationTime
;
4851 atime
= info
.ftLastAccessTime
;
4852 wtime
= info
.ftLastWriteTime
;
4853 fattrs
= info
.dwFileAttributes
;
4857 /* We don't go to Plan B here, because it's not clear that
4858 it's a good idea. The only known use case where
4859 CreateFile succeeds, but GetFileInformationByHandle fails
4860 (with ERROR_INVALID_FUNCTION) is for character devices
4861 such as NUL, PRN, etc. For these, switching to Plan B is
4862 a net loss, because we lose the character device
4863 attribute returned by GetFileType below (FindFirstFile
4864 doesn't set that bit in the attributes), and the other
4865 fields don't make sense for character devices anyway.
4866 Emacs doesn't really care for non-file entities in the
4867 context of l?stat, so neither do we. */
4869 /* w32err is assigned so one could put a breakpoint here and
4870 examine its value, when GetFileInformationByHandle
4872 DWORD w32err
= GetLastError ();
4876 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4882 /* Test for a symlink before testing for a directory, since
4883 symlinks to directories have the directory bit set, but we
4884 don't want them to appear as directories. */
4885 if (is_a_symlink
&& !follow_symlinks
)
4886 buf
->st_mode
= S_IFLNK
;
4887 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4888 buf
->st_mode
= S_IFDIR
;
4891 DWORD ftype
= GetFileType (fh
);
4895 case FILE_TYPE_DISK
:
4896 buf
->st_mode
= S_IFREG
;
4898 case FILE_TYPE_PIPE
:
4899 buf
->st_mode
= S_IFIFO
;
4901 case FILE_TYPE_CHAR
:
4902 case FILE_TYPE_UNKNOWN
:
4904 buf
->st_mode
= S_IFCHR
;
4907 /* We produce the fallback owner and group data, based on the
4908 current user that runs Emacs, in the following cases:
4910 . caller didn't request owner and group info
4911 . this is Windows 9X
4912 . getting security by handle failed, and we need to produce
4913 information for the target of a symlink (this is better
4914 than producing a potentially misleading info about the
4917 If getting security by handle fails, and we don't need to
4918 resolve symlinks, we try getting security by name. */
4919 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4920 get_file_owner_and_group (NULL
, buf
);
4923 psd
= get_file_security_desc_by_handle (fh
);
4926 get_file_owner_and_group (psd
, buf
);
4929 else if (!(is_a_symlink
&& follow_symlinks
))
4931 psd
= get_file_security_desc_by_name (name
);
4932 get_file_owner_and_group (psd
, buf
);
4936 get_file_owner_and_group (NULL
, buf
);
4942 no_true_file_attributes
:
4943 /* Plan B: Either getting a handle on the file failed, or the
4944 caller explicitly asked us to not bother making this
4945 information more accurate.
4947 Implementation note: In Plan B, we never bother to resolve
4948 symlinks, even if we got here because we tried Plan A and
4949 failed. That's because, even if the caller asked for extra
4950 precision by setting Vw32_get_true_file_attributes to t,
4951 resolving symlinks requires acquiring a file handle to the
4952 symlink, which we already know will fail. And if the user
4953 did not ask for extra precision, resolving symlinks will fly
4954 in the face of that request, since the user then wants the
4955 lightweight version of the code. */
4956 rootdir
= (path
>= save_name
+ len
- 1
4957 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4959 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4960 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4961 if (IS_DIRECTORY_SEP (r
[0])
4962 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4965 /* Note: If NAME is a symlink to the root of a UNC volume
4966 (i.e. "\\SERVER"), we will not detect that here, and we will
4967 return data about the symlink as result of FindFirst below.
4968 This is unfortunate, but that marginal use case does not
4969 justify a call to chase_symlinks which would impose a penalty
4970 on all the other use cases. (We get here for symlinks to
4971 roots of UNC volumes because CreateFile above fails for them,
4972 unlike with symlinks to root directories X:\ of drives.) */
4973 if (is_unc_volume (name
))
4975 fattrs
= unc_volume_file_attributes (name
);
4979 ctime
= atime
= wtime
= utc_base_ft
;
4983 /* Make sure root directories end in a slash. */
4984 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4985 strcpy (name
+ len
, "\\");
4986 if (GetDriveType (name
) < 2)
4992 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4993 ctime
= atime
= wtime
= utc_base_ft
;
4999 /* Make sure non-root directories do NOT end in a slash,
5000 otherwise FindFirstFile might fail. */
5001 if (IS_DIRECTORY_SEP (name
[len
-1]))
5004 /* (This is hacky, but helps when doing file completions on
5005 network drives.) Optimize by using information available from
5006 active readdir if possible. */
5007 len
= strlen (dir_pathname
);
5008 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
5010 if (dir_find_handle
!= INVALID_HANDLE_VALUE
5011 && last_dir_find_data
!= -1
5012 && !(is_a_symlink
&& follow_symlinks
)
5013 /* The 2 file-name comparisons below support only ASCII
5014 characters, and will lose (compare not equal) when
5015 the file names include non-ASCII characters that are
5016 the same but for the case. However, doing this
5017 properly involves: (a) converting both file names to
5018 UTF-16, (b) lower-casing both names using CharLowerW,
5019 and (c) comparing the results; this would be quite a
5020 bit slower, whereas Plan B is for users who want
5021 lightweight albeit inaccurate version of 'stat'. */
5022 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5023 && IS_DIRECTORY_SEP (name
[len
])
5024 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5026 have_wfd
= last_dir_find_data
;
5027 /* This was the last entry returned by readdir. */
5028 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5029 wfd_w
= dir_find_data_w
;
5031 wfd_a
= dir_find_data_a
;
5035 logon_network_drive (name
);
5037 if (w32_unicode_filenames
)
5039 filename_to_utf16 (name
, name_w
);
5040 fh
= FindFirstFileW (name_w
, &wfd_w
);
5041 have_wfd
= DIR_FIND_DATA_W
;
5045 filename_to_ansi (name
, name_a
);
5046 /* If NAME includes characters not representable by
5047 the current ANSI codepage, filename_to_ansi
5048 usually replaces them with a '?'. We don't want
5049 to let FindFirstFileA interpret those as wildcards,
5050 and "succeed", returning us data from some random
5051 file in the same directory. */
5052 if (_mbspbrk (name_a
, "?"))
5053 fh
= INVALID_HANDLE_VALUE
;
5055 fh
= FindFirstFileA (name_a
, &wfd_a
);
5056 have_wfd
= DIR_FIND_DATA_A
;
5058 if (fh
== INVALID_HANDLE_VALUE
)
5065 /* Note: if NAME is a symlink, the information we get from
5066 FindFirstFile is for the symlink, not its target. */
5067 if (have_wfd
== DIR_FIND_DATA_W
)
5069 fattrs
= wfd_w
.dwFileAttributes
;
5070 ctime
= wfd_w
.ftCreationTime
;
5071 atime
= wfd_w
.ftLastAccessTime
;
5072 wtime
= wfd_w
.ftLastWriteTime
;
5073 fs_high
= wfd_w
.nFileSizeHigh
;
5074 fs_low
= wfd_w
.nFileSizeLow
;
5078 fattrs
= wfd_a
.dwFileAttributes
;
5079 ctime
= wfd_a
.ftCreationTime
;
5080 atime
= wfd_a
.ftLastAccessTime
;
5081 wtime
= wfd_a
.ftLastWriteTime
;
5082 fs_high
= wfd_a
.nFileSizeHigh
;
5083 fs_low
= wfd_a
.nFileSizeLow
;
5087 serialnum
= volume_info
.serialnum
;
5089 if (is_a_symlink
&& !follow_symlinks
)
5090 buf
->st_mode
= S_IFLNK
;
5091 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5092 buf
->st_mode
= S_IFDIR
;
5094 buf
->st_mode
= S_IFREG
;
5096 get_file_owner_and_group (NULL
, buf
);
5099 buf
->st_ino
= fake_inode
;
5101 buf
->st_dev
= serialnum
;
5102 buf
->st_rdev
= serialnum
;
5104 buf
->st_size
= fs_high
;
5105 buf
->st_size
<<= 32;
5106 buf
->st_size
+= fs_low
;
5107 buf
->st_nlink
= nlinks
;
5109 /* Convert timestamps to Unix format. */
5110 buf
->st_mtime
= convert_time (wtime
);
5111 buf
->st_atime
= convert_time (atime
);
5112 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5113 buf
->st_ctime
= convert_time (ctime
);
5114 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5116 /* determine rwx permissions */
5117 if (is_a_symlink
&& !follow_symlinks
)
5118 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5121 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5122 permission
= S_IREAD
;
5124 permission
= S_IREAD
| S_IWRITE
;
5126 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5127 permission
|= S_IEXEC
;
5128 else if (is_exec (name
))
5129 permission
|= S_IEXEC
;
5132 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5138 stat (const char * path
, struct stat
* buf
)
5140 return stat_worker (path
, buf
, 1);
5144 lstat (const char * path
, struct stat
* buf
)
5146 return stat_worker (path
, buf
, 0);
5150 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5152 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5153 This is good enough for the current usage in Emacs, but is fragile.
5155 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5156 Gnulib does this and can serve as a model. */
5157 char fullname
[MAX_UTF8_PATH
];
5161 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5163 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5164 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5167 errno
= ENAMETOOLONG
;
5173 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5176 /* Provide fstat and utime as well as stat for consistent handling of
5179 fstat (int desc
, struct stat
* buf
)
5181 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5182 BY_HANDLE_FILE_INFORMATION info
;
5183 unsigned __int64 fake_inode
;
5186 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5188 case FILE_TYPE_DISK
:
5189 buf
->st_mode
= S_IFREG
;
5190 if (!GetFileInformationByHandle (fh
, &info
))
5196 case FILE_TYPE_PIPE
:
5197 buf
->st_mode
= S_IFIFO
;
5199 case FILE_TYPE_CHAR
:
5200 case FILE_TYPE_UNKNOWN
:
5202 buf
->st_mode
= S_IFCHR
;
5204 memset (&info
, 0, sizeof (info
));
5205 info
.dwFileAttributes
= 0;
5206 info
.ftCreationTime
= utc_base_ft
;
5207 info
.ftLastAccessTime
= utc_base_ft
;
5208 info
.ftLastWriteTime
= utc_base_ft
;
5211 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5212 buf
->st_mode
= S_IFDIR
;
5214 buf
->st_nlink
= info
.nNumberOfLinks
;
5215 /* Might as well use file index to fake inode values, but this
5216 is not guaranteed to be unique unless we keep a handle open
5217 all the time (even then there are situations where it is
5218 not unique). Reputedly, there are at most 48 bits of info
5219 (on NTFS, presumably less on FAT). */
5220 fake_inode
= info
.nFileIndexHigh
;
5222 fake_inode
+= info
.nFileIndexLow
;
5224 /* MSVC defines _ino_t to be short; other libc's might not. */
5225 if (sizeof (buf
->st_ino
) == 2)
5226 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5228 buf
->st_ino
= fake_inode
;
5230 /* If the caller so requested, get the true file owner and group.
5231 Otherwise, consider the file to belong to the current user. */
5232 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5233 get_file_owner_and_group (NULL
, buf
);
5236 PSECURITY_DESCRIPTOR psd
= NULL
;
5238 psd
= get_file_security_desc_by_handle (fh
);
5241 get_file_owner_and_group (psd
, buf
);
5245 get_file_owner_and_group (NULL
, buf
);
5248 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5249 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5251 buf
->st_size
= info
.nFileSizeHigh
;
5252 buf
->st_size
<<= 32;
5253 buf
->st_size
+= info
.nFileSizeLow
;
5255 /* Convert timestamps to Unix format. */
5256 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5257 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5258 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5259 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5260 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5262 /* determine rwx permissions */
5263 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5264 permission
= S_IREAD
;
5266 permission
= S_IREAD
| S_IWRITE
;
5268 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5269 permission
|= S_IEXEC
;
5272 #if 0 /* no way of knowing the filename */
5273 char * p
= strrchr (name
, '.');
5275 (xstrcasecmp (p
, ".exe") == 0 ||
5276 xstrcasecmp (p
, ".com") == 0 ||
5277 xstrcasecmp (p
, ".bat") == 0 ||
5278 xstrcasecmp (p
, ".cmd") == 0))
5279 permission
|= S_IEXEC
;
5283 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5288 /* A version of 'utime' which handles directories as well as
5292 utime (const char *name
, struct utimbuf
*times
)
5294 struct utimbuf deftime
;
5301 deftime
.modtime
= deftime
.actime
= time (NULL
);
5305 if (w32_unicode_filenames
)
5307 wchar_t name_utf16
[MAX_PATH
];
5309 if (filename_to_utf16 (name
, name_utf16
) != 0)
5310 return -1; /* errno set by filename_to_utf16 */
5312 /* Need write access to set times. */
5313 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5314 /* If NAME specifies a directory, FILE_SHARE_DELETE
5315 allows other processes to delete files inside it,
5316 while we have the directory open. */
5317 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5318 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5322 char name_ansi
[MAX_PATH
];
5324 if (filename_to_ansi (name
, name_ansi
) != 0)
5325 return -1; /* errno set by filename_to_ansi */
5327 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5328 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5329 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5331 if (fh
!= INVALID_HANDLE_VALUE
)
5333 convert_from_time_t (times
->actime
, &atime
);
5334 convert_from_time_t (times
->modtime
, &mtime
);
5335 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5345 DWORD err
= GetLastError ();
5349 case ERROR_FILE_NOT_FOUND
:
5350 case ERROR_PATH_NOT_FOUND
:
5351 case ERROR_INVALID_DRIVE
:
5352 case ERROR_BAD_NETPATH
:
5353 case ERROR_DEV_NOT_EXIST
:
5354 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5355 file name includes ?s, i.e. translation to ANSI failed. */
5356 case ERROR_INVALID_NAME
:
5359 case ERROR_TOO_MANY_OPEN_FILES
:
5362 case ERROR_ACCESS_DENIED
:
5363 case ERROR_SHARING_VIOLATION
:
5376 sys_umask (int mode
)
5378 static int current_mask
;
5379 int retval
, arg
= 0;
5381 /* The only bit we really support is the write bit. Files are
5382 always readable on MS-Windows, and the execute bit does not exist
5384 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5385 to prevent access by other users on NTFS. */
5386 if ((mode
& S_IWRITE
) != 0)
5389 retval
= _umask (arg
);
5390 /* Merge into the return value the bits they've set the last time,
5391 which msvcrt.dll ignores and never returns. Emacs insists on its
5392 notion of mask being identical to what we return. */
5393 retval
|= (current_mask
& ~S_IWRITE
);
5394 current_mask
= mode
;
5400 /* Symlink-related functions. */
5401 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5402 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5406 symlink (char const *filename
, char const *linkname
)
5408 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5410 int dir_access
, filename_ends_in_slash
;
5412 /* Diagnostics follows Posix as much as possible. */
5413 if (filename
== NULL
|| linkname
== NULL
)
5423 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5425 errno
= ENAMETOOLONG
;
5429 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5430 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5436 /* Note: since empty FILENAME was already rejected, we can safely
5437 refer to FILENAME[1]. */
5438 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5440 /* Non-absolute FILENAME is understood as being relative to
5441 LINKNAME's directory. We need to prepend that directory to
5442 FILENAME to get correct results from faccessat below, since
5443 otherwise it will interpret FILENAME relative to the
5444 directory where the Emacs process runs. Note that
5445 make-symbolic-link always makes sure LINKNAME is a fully
5446 expanded file name. */
5447 char tem
[MAX_UTF8_PATH
];
5448 char *p
= linkfn
+ strlen (linkfn
);
5450 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5453 strncpy (tem
, linkfn
, p
- linkfn
);
5454 strcpy (tem
+ (p
- linkfn
), filename
);
5455 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5458 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5460 /* Since Windows distinguishes between symlinks to directories and
5461 to files, we provide a kludgy feature: if FILENAME doesn't
5462 exist, but ends in a slash, we create a symlink to directory. If
5463 FILENAME exists and is a directory, we always create a symlink to
5465 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5466 if (dir_access
== 0 || filename_ends_in_slash
)
5467 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5469 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5470 if (filename_ends_in_slash
)
5471 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5474 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5476 /* ENOSYS is set by create_symbolic_link, when it detects that
5477 the OS doesn't support the CreateSymbolicLink API. */
5478 if (errno
!= ENOSYS
)
5480 DWORD w32err
= GetLastError ();
5484 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5485 TGTFN point to the same file name, go figure. */
5487 case ERROR_FILE_EXISTS
:
5490 case ERROR_ACCESS_DENIED
:
5493 case ERROR_FILE_NOT_FOUND
:
5494 case ERROR_PATH_NOT_FOUND
:
5495 case ERROR_BAD_NETPATH
:
5496 case ERROR_INVALID_REPARSE_DATA
:
5499 case ERROR_DIRECTORY
:
5502 case ERROR_PRIVILEGE_NOT_HELD
:
5503 case ERROR_NOT_ALL_ASSIGNED
:
5506 case ERROR_DISK_FULL
:
5519 /* A quick inexpensive test of whether FILENAME identifies a file that
5520 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5521 must already be in the normalized form returned by
5524 Note: for repeated operations on many files, it is best to test
5525 whether the underlying volume actually supports symlinks, by
5526 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5527 avoid the call to this function if it doesn't. That's because the
5528 call to GetFileAttributes takes a non-negligible time, especially
5529 on non-local or removable filesystems. See stat_worker for an
5530 example of how to do that. */
5532 is_symlink (const char *filename
)
5535 wchar_t filename_w
[MAX_PATH
];
5536 char filename_a
[MAX_PATH
];
5537 WIN32_FIND_DATAW wfdw
;
5538 WIN32_FIND_DATAA wfda
;
5540 int attrs_mean_symlink
;
5542 if (w32_unicode_filenames
)
5544 filename_to_utf16 (filename
, filename_w
);
5545 attrs
= GetFileAttributesW (filename_w
);
5549 filename_to_ansi (filename
, filename_a
);
5550 attrs
= GetFileAttributesA (filename_a
);
5554 DWORD w32err
= GetLastError ();
5558 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5560 case ERROR_ACCESS_DENIED
:
5563 case ERROR_FILE_NOT_FOUND
:
5564 case ERROR_PATH_NOT_FOUND
:
5571 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5573 logon_network_drive (filename
);
5574 if (w32_unicode_filenames
)
5576 fh
= FindFirstFileW (filename_w
, &wfdw
);
5577 attrs_mean_symlink
=
5578 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5579 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5581 else if (_mbspbrk (filename_a
, "?"))
5583 /* filename_to_ansi failed to convert the file name. */
5589 fh
= FindFirstFileA (filename_a
, &wfda
);
5590 attrs_mean_symlink
=
5591 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5592 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5594 if (fh
== INVALID_HANDLE_VALUE
)
5597 return attrs_mean_symlink
;
5600 /* If NAME identifies a symbolic link, copy into BUF the file name of
5601 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5602 null-terminate the target name, even if it fits. Return the number
5603 of bytes copied, or -1 if NAME is not a symlink or any error was
5604 encountered while resolving it. The file name copied into BUF is
5605 encoded in the current ANSI codepage. */
5607 readlink (const char *name
, char *buf
, size_t buf_size
)
5610 TOKEN_PRIVILEGES privs
;
5611 int restore_privs
= 0;
5614 char resolved
[MAX_UTF8_PATH
];
5627 path
= map_w32_filename (name
, NULL
);
5629 if (strlen (path
) > MAX_UTF8_PATH
)
5631 errno
= ENAMETOOLONG
;
5636 if (is_windows_9x () == TRUE
5637 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5638 || !is_symlink (path
))
5641 errno
= EINVAL
; /* not a symlink */
5645 /* Done with simple tests, now we're in for some _real_ work. */
5646 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5648 /* Implementation note: From here and onward, don't return early,
5649 since that will fail to restore the original set of privileges of
5650 the calling thread. */
5652 retval
= -1; /* not too optimistic, are we? */
5654 /* Note: In the next call to CreateFile, we use zero as the 2nd
5655 argument because, when the symlink is a hidden/system file,
5656 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5657 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5658 and directory symlinks. */
5659 if (w32_unicode_filenames
)
5661 wchar_t path_w
[MAX_PATH
];
5663 filename_to_utf16 (path
, path_w
);
5664 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5665 FILE_FLAG_OPEN_REPARSE_POINT
5666 | FILE_FLAG_BACKUP_SEMANTICS
,
5671 char path_a
[MAX_PATH
];
5673 filename_to_ansi (path
, path_a
);
5674 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5675 FILE_FLAG_OPEN_REPARSE_POINT
5676 | FILE_FLAG_BACKUP_SEMANTICS
,
5679 if (sh
!= INVALID_HANDLE_VALUE
)
5681 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5682 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5685 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5686 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5689 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5693 /* Copy the link target name, in wide characters, from
5694 reparse_data, then convert it to multibyte encoding in
5695 the current locale's codepage. */
5699 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5701 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5702 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5703 size_t size_to_copy
= buf_size
;
5705 /* According to MSDN, PrintNameLength does not include the
5706 terminating null character. */
5707 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5708 memcpy (lwname
, lwname_src
, lwname_len
);
5709 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5710 filename_from_utf16 (lwname
, resolved
);
5711 dostounix_filename (resolved
);
5712 lname_size
= strlen (resolved
) + 1;
5713 if (lname_size
<= buf_size
)
5714 size_to_copy
= lname_size
;
5715 strncpy (buf
, resolved
, size_to_copy
);
5717 retval
= size_to_copy
;
5723 /* CreateFile failed. */
5724 DWORD w32err2
= GetLastError ();
5728 case ERROR_FILE_NOT_FOUND
:
5729 case ERROR_PATH_NOT_FOUND
:
5732 case ERROR_ACCESS_DENIED
:
5733 case ERROR_TOO_MANY_OPEN_FILES
:
5743 restore_privilege (&privs
);
5751 readlinkat (int fd
, char const *name
, char *buffer
,
5754 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5755 as in fstatat. FIXME: Add proper support for readlinkat. */
5756 char fullname
[MAX_UTF8_PATH
];
5760 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5763 errno
= ENAMETOOLONG
;
5769 return readlink (name
, buffer
, buffer_size
);
5772 /* If FILE is a symlink, return its target (stored in a static
5773 buffer); otherwise return FILE.
5775 This function repeatedly resolves symlinks in the last component of
5776 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5777 until it arrives at a file whose last component is not a symlink,
5778 or some error occurs. It returns the target of the last
5779 successfully resolved symlink in the chain. If it succeeds to
5780 resolve even a single symlink, the value returned is an absolute
5781 file name with backslashes (result of GetFullPathName). By
5782 contrast, if the original FILE is returned, it is unaltered.
5784 Note: This function can set errno even if it succeeds.
5786 Implementation note: we only resolve the last portion ("basename")
5787 of the argument FILE and of each following file in the chain,
5788 disregarding any possible symlinks in its leading directories.
5789 This is because Windows system calls and library functions
5790 transparently resolve symlinks in leading directories and return
5791 correct information, as long as the basename is not a symlink. */
5793 chase_symlinks (const char *file
)
5795 static char target
[MAX_UTF8_PATH
];
5796 char link
[MAX_UTF8_PATH
];
5797 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5798 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5799 ssize_t res
, link_len
;
5802 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5803 return (char *)file
;
5805 if (w32_unicode_filenames
)
5807 wchar_t file_w
[MAX_PATH
];
5809 filename_to_utf16 (file
, file_w
);
5810 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5811 return (char *)file
;
5812 filename_from_utf16 (link_w
, link
);
5816 char file_a
[MAX_PATH
];
5818 filename_to_ansi (file
, file_a
);
5819 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5820 return (char *)file
;
5821 filename_from_ansi (link_a
, link
);
5823 link_len
= strlen (link
);
5828 /* Remove trailing slashes, as we want to resolve the last
5829 non-trivial part of the link name. */
5830 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5831 link
[link_len
--] = '\0';
5833 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5837 if (!(IS_DEVICE_SEP (target
[1])
5838 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5840 /* Target is relative. Append it to the directory part of
5841 the symlink, then copy the result back to target. */
5842 char *p
= link
+ link_len
;
5844 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5847 strcpy (target
, link
);
5849 /* Resolve any "." and ".." to get a fully-qualified file name
5851 if (w32_unicode_filenames
)
5853 filename_to_utf16 (target
, target_w
);
5854 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5856 filename_from_utf16 (link_w
, link
);
5860 filename_to_ansi (target
, target_a
);
5861 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5863 filename_from_ansi (link_a
, link
);
5865 link_len
= strlen (link
);
5867 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5869 if (loop_count
> 100)
5872 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5873 return (char *)file
;
5878 /* Posix ACL emulation. */
5881 acl_valid (acl_t acl
)
5883 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5887 acl_to_text (acl_t acl
, ssize_t
*size
)
5890 SECURITY_INFORMATION flags
=
5891 OWNER_SECURITY_INFORMATION
|
5892 GROUP_SECURITY_INFORMATION
|
5893 DACL_SECURITY_INFORMATION
;
5894 char *retval
= NULL
;
5900 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5903 /* We don't want to mix heaps, so we duplicate the string in our
5904 heap and free the one allocated by the API. */
5905 retval
= xstrdup (str_acl
);
5908 LocalFree (str_acl
);
5910 else if (errno
!= ENOTSUP
)
5917 acl_from_text (const char *acl_str
)
5919 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5925 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5928 retval
= xmalloc (sd_size
);
5929 memcpy (retval
, psd
, sd_size
);
5932 else if (errno
!= ENOTSUP
)
5939 acl_free (void *ptr
)
5946 acl_get_file (const char *fname
, acl_type_t type
)
5948 PSECURITY_DESCRIPTOR psd
= NULL
;
5949 const char *filename
;
5951 if (type
== ACL_TYPE_ACCESS
)
5954 SECURITY_INFORMATION si
=
5955 OWNER_SECURITY_INFORMATION
|
5956 GROUP_SECURITY_INFORMATION
|
5957 DACL_SECURITY_INFORMATION
;
5960 filename
= map_w32_filename (fname
, NULL
);
5961 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5962 fname
= chase_symlinks (filename
);
5967 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5968 && errno
!= ENOTSUP
)
5970 err
= GetLastError ();
5971 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5973 psd
= xmalloc (sd_len
);
5974 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5981 else if (err
== ERROR_FILE_NOT_FOUND
5982 || err
== ERROR_PATH_NOT_FOUND
5983 /* ERROR_INVALID_NAME is what we get if
5984 w32-unicode-filenames is nil and the file cannot
5985 be encoded in the current ANSI codepage. */
5986 || err
== ERROR_INVALID_NAME
)
5994 else if (type
!= ACL_TYPE_DEFAULT
)
6001 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
6003 TOKEN_PRIVILEGES old1
, old2
;
6005 int st
= 0, retval
= -1;
6006 SECURITY_INFORMATION flags
= 0;
6007 PSID psidOwner
, psidGroup
;
6012 const char *filename
;
6014 if (acl_valid (acl
) != 0
6015 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6021 if (type
== ACL_TYPE_DEFAULT
)
6027 filename
= map_w32_filename (fname
, NULL
);
6028 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6029 fname
= chase_symlinks (filename
);
6033 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6036 flags
|= OWNER_SECURITY_INFORMATION
;
6037 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6040 flags
|= GROUP_SECURITY_INFORMATION
;
6041 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6044 flags
|= DACL_SECURITY_INFORMATION
;
6048 /* According to KB-245153, setting the owner will succeed if either:
6049 (1) the caller is the user who will be the new owner, and has the
6050 SE_TAKE_OWNERSHIP privilege, or
6051 (2) the caller has the SE_RESTORE privilege, in which case she can
6052 set any valid user or group as the owner
6054 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6055 privileges, and disregard any failures in obtaining them. If
6056 these privileges cannot be obtained, and do not already exist in
6057 the calling thread's security token, this function could fail
6059 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6061 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6066 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6067 DACL inheritance is involved, but it seems to preserve ownership
6068 better than SetNamedSecurityInfo, which is important e.g., in
6070 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6072 err
= GetLastError ();
6074 if (errno
!= ENOTSUP
)
6075 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6076 psidOwner
, psidGroup
, pacl
, NULL
);
6079 err
= ERROR_SUCCESS
;
6080 if (err
!= ERROR_SUCCESS
)
6082 if (errno
== ENOTSUP
)
6084 else if (err
== ERROR_INVALID_OWNER
6085 || err
== ERROR_NOT_ALL_ASSIGNED
6086 || err
== ERROR_ACCESS_DENIED
)
6088 /* Maybe the requested ACL and the one the file already has
6089 are identical, in which case we can silently ignore the
6090 failure. (And no, Windows doesn't.) */
6091 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6096 char *acl_from
= acl_to_text (current_acl
, NULL
);
6097 char *acl_to
= acl_to_text (acl
, NULL
);
6099 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6105 acl_free (acl_from
);
6108 acl_free (current_acl
);
6111 else if (err
== ERROR_FILE_NOT_FOUND
6112 || err
== ERROR_PATH_NOT_FOUND
6113 /* ERROR_INVALID_NAME is what we get if
6114 w32-unicode-filenames is nil and the file cannot be
6115 encoded in the current ANSI codepage. */
6116 || err
== ERROR_INVALID_NAME
)
6130 restore_privilege (&old2
);
6131 restore_privilege (&old1
);
6139 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6140 have a fixed max size for file names, so we don't need the kind of
6141 alloc/malloc/realloc dance the gnulib version does. We also don't
6142 support FD-relative symlinks. */
6144 careadlinkat (int fd
, char const *filename
,
6145 char *buffer
, size_t buffer_size
,
6146 struct allocator
const *alloc
,
6147 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6149 char linkname
[MAX_UTF8_PATH
];
6152 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6156 char *retval
= buffer
;
6158 linkname
[link_size
++] = '\0';
6159 if (link_size
> buffer_size
)
6160 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6162 memcpy (retval
, linkname
, link_size
);
6170 w32_copy_file (const char *from
, const char *to
,
6171 int keep_time
, int preserve_ownership
, int copy_acls
)
6175 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6176 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6178 /* We ignore preserve_ownership for now. */
6179 preserve_ownership
= preserve_ownership
;
6183 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6184 if (acl
== NULL
&& acl_errno_valid (errno
))
6187 if (w32_unicode_filenames
)
6189 filename_to_utf16 (from
, from_w
);
6190 filename_to_utf16 (to
, to_w
);
6191 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6195 filename_to_ansi (from
, from_a
);
6196 filename_to_ansi (to
, to_a
);
6197 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6201 /* CopyFile doesn't set errno when it fails. By far the most
6202 "popular" reason is that the target is read-only. */
6203 DWORD err
= GetLastError ();
6207 case ERROR_FILE_NOT_FOUND
:
6210 case ERROR_ACCESS_DENIED
:
6213 case ERROR_ENCRYPTION_FAILED
:
6225 /* CopyFile retains the timestamp by default. However, see
6226 "Community Additions" for CopyFile: it sounds like that is not
6227 entirely true. Testing on Windows XP confirms that modified time
6228 is copied, but creation and last-access times are not.
6230 else if (!keep_time
)
6232 struct timespec now
;
6235 if (w32_unicode_filenames
)
6237 /* Ensure file is writable while its times are set. */
6238 attributes
= GetFileAttributesW (to_w
);
6239 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6240 now
= current_timespec ();
6241 if (set_file_times (-1, to
, now
, now
))
6243 /* Restore original attributes. */
6244 SetFileAttributesW (to_w
, attributes
);
6249 /* Restore original attributes. */
6250 SetFileAttributesW (to_w
, attributes
);
6254 attributes
= GetFileAttributesA (to_a
);
6255 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6256 now
= current_timespec ();
6257 if (set_file_times (-1, to
, now
, now
))
6259 SetFileAttributesA (to_a
, attributes
);
6264 SetFileAttributesA (to_a
, attributes
);
6270 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6272 if (fail
&& acl_errno_valid (errno
))
6280 /* Support for browsing other processes and their attributes. See
6281 process.c for the Lisp bindings. */
6283 /* Helper wrapper functions. */
6285 static HANDLE WINAPI
6286 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6288 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6290 if (g_b_init_create_toolhelp32_snapshot
== 0)
6292 g_b_init_create_toolhelp32_snapshot
= 1;
6293 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6294 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6295 "CreateToolhelp32Snapshot");
6297 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6299 return INVALID_HANDLE_VALUE
;
6301 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6305 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6307 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6309 if (g_b_init_process32_first
== 0)
6311 g_b_init_process32_first
= 1;
6312 s_pfn_Process32_First
= (Process32First_Proc
)
6313 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6316 if (s_pfn_Process32_First
== NULL
)
6320 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6324 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6326 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6328 if (g_b_init_process32_next
== 0)
6330 g_b_init_process32_next
= 1;
6331 s_pfn_Process32_Next
= (Process32Next_Proc
)
6332 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6335 if (s_pfn_Process32_Next
== NULL
)
6339 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6343 open_thread_token (HANDLE ThreadHandle
,
6344 DWORD DesiredAccess
,
6346 PHANDLE TokenHandle
)
6348 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6349 HMODULE hm_advapi32
= NULL
;
6350 if (is_windows_9x () == TRUE
)
6352 SetLastError (ERROR_NOT_SUPPORTED
);
6355 if (g_b_init_open_thread_token
== 0)
6357 g_b_init_open_thread_token
= 1;
6358 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6359 s_pfn_Open_Thread_Token
=
6360 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6362 if (s_pfn_Open_Thread_Token
== NULL
)
6364 SetLastError (ERROR_NOT_SUPPORTED
);
6368 s_pfn_Open_Thread_Token (
6377 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6379 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6380 HMODULE hm_advapi32
= NULL
;
6381 if (is_windows_9x () == TRUE
)
6385 if (g_b_init_impersonate_self
== 0)
6387 g_b_init_impersonate_self
= 1;
6388 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6389 s_pfn_Impersonate_Self
=
6390 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6392 if (s_pfn_Impersonate_Self
== NULL
)
6396 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6400 revert_to_self (void)
6402 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6403 HMODULE hm_advapi32
= NULL
;
6404 if (is_windows_9x () == TRUE
)
6408 if (g_b_init_revert_to_self
== 0)
6410 g_b_init_revert_to_self
= 1;
6411 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6412 s_pfn_Revert_To_Self
=
6413 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6415 if (s_pfn_Revert_To_Self
== NULL
)
6419 return s_pfn_Revert_To_Self ();
6423 get_process_memory_info (HANDLE h_proc
,
6424 PPROCESS_MEMORY_COUNTERS mem_counters
,
6427 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6428 HMODULE hm_psapi
= NULL
;
6429 if (is_windows_9x () == TRUE
)
6433 if (g_b_init_get_process_memory_info
== 0)
6435 g_b_init_get_process_memory_info
= 1;
6436 hm_psapi
= LoadLibrary ("Psapi.dll");
6438 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6439 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6441 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6445 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6449 get_process_working_set_size (HANDLE h_proc
,
6453 static GetProcessWorkingSetSize_Proc
6454 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6456 if (is_windows_9x () == TRUE
)
6460 if (g_b_init_get_process_working_set_size
== 0)
6462 g_b_init_get_process_working_set_size
= 1;
6463 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6464 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6465 "GetProcessWorkingSetSize");
6467 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6471 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6475 global_memory_status (MEMORYSTATUS
*buf
)
6477 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6479 if (is_windows_9x () == TRUE
)
6483 if (g_b_init_global_memory_status
== 0)
6485 g_b_init_global_memory_status
= 1;
6486 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6487 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6488 "GlobalMemoryStatus");
6490 if (s_pfn_Global_Memory_Status
== NULL
)
6494 return s_pfn_Global_Memory_Status (buf
);
6498 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6500 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6502 if (is_windows_9x () == TRUE
)
6506 if (g_b_init_global_memory_status_ex
== 0)
6508 g_b_init_global_memory_status_ex
= 1;
6509 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6510 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6511 "GlobalMemoryStatusEx");
6513 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6517 return s_pfn_Global_Memory_Status_Ex (buf
);
6521 list_system_processes (void)
6523 struct gcpro gcpro1
;
6524 Lisp_Object proclist
= Qnil
;
6527 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6529 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6531 PROCESSENTRY32 proc_entry
;
6537 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6538 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6539 res
= process32_next (h_snapshot
, &proc_entry
))
6541 proc_id
= proc_entry
.th32ProcessID
;
6542 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6545 CloseHandle (h_snapshot
);
6547 proclist
= Fnreverse (proclist
);
6554 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6556 TOKEN_PRIVILEGES priv
;
6557 DWORD priv_size
= sizeof (priv
);
6558 DWORD opriv_size
= sizeof (*old_priv
);
6559 HANDLE h_token
= NULL
;
6560 HANDLE h_thread
= GetCurrentThread ();
6564 res
= open_thread_token (h_thread
,
6565 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6567 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6569 if (impersonate_self (SecurityImpersonation
))
6570 res
= open_thread_token (h_thread
,
6571 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6576 priv
.PrivilegeCount
= 1;
6577 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6578 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6579 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6580 old_priv
, &opriv_size
)
6581 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6585 CloseHandle (h_token
);
6591 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6593 DWORD priv_size
= sizeof (*priv
);
6594 HANDLE h_token
= NULL
;
6597 if (open_thread_token (GetCurrentThread (),
6598 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6601 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6602 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6606 CloseHandle (h_token
);
6612 ltime (ULONGLONG time_100ns
)
6614 ULONGLONG time_sec
= time_100ns
/ 10000000;
6615 int subsec
= time_100ns
% 10000000;
6616 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6617 subsec
/ 10, subsec
% 10 * 100000);
6620 #define U64_TO_LISP_TIME(time) ltime (time)
6623 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6624 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6627 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6628 ULONGLONG tem1
, tem2
, tem3
, tem
;
6631 || !get_process_times_fn
6632 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6633 &ft_kernel
, &ft_user
))
6636 GetSystemTimeAsFileTime (&ft_current
);
6638 FILETIME_TO_U64 (tem1
, ft_kernel
);
6639 *stime
= U64_TO_LISP_TIME (tem1
);
6641 FILETIME_TO_U64 (tem2
, ft_user
);
6642 *utime
= U64_TO_LISP_TIME (tem2
);
6645 *ttime
= U64_TO_LISP_TIME (tem3
);
6647 FILETIME_TO_U64 (tem
, ft_creation
);
6648 /* Process no 4 (System) returns zero creation time. */
6651 *ctime
= U64_TO_LISP_TIME (tem
);
6655 FILETIME_TO_U64 (tem3
, ft_current
);
6656 tem
= (tem3
- utc_base
) - tem
;
6658 *etime
= U64_TO_LISP_TIME (tem
);
6662 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6673 system_process_attributes (Lisp_Object pid
)
6675 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6676 Lisp_Object attrs
= Qnil
;
6677 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6678 HANDLE h_snapshot
, h_proc
;
6681 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6682 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6683 DWORD glength
= sizeof (gname
);
6684 HANDLE token
= NULL
;
6685 SID_NAME_USE user_type
;
6686 unsigned char *buf
= NULL
;
6688 TOKEN_USER user_token
;
6689 TOKEN_PRIMARY_GROUP group_token
;
6692 PROCESS_MEMORY_COUNTERS mem
;
6693 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6694 SIZE_T minrss
, maxrss
;
6696 MEMORY_STATUS_EX memstex
;
6697 double totphys
= 0.0;
6698 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6700 BOOL result
= FALSE
;
6702 CHECK_NUMBER_OR_FLOAT (pid
);
6703 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6705 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6707 GCPRO3 (attrs
, decoded_cmd
, tem
);
6709 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6714 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6715 for (res
= process32_first (h_snapshot
, &pe
); res
;
6716 res
= process32_next (h_snapshot
, &pe
))
6718 if (proc_id
== pe
.th32ProcessID
)
6721 decoded_cmd
= build_string ("Idle");
6724 /* Decode the command name from locale-specific
6726 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6729 code_convert_string_norecord (cmd_str
,
6730 Vlocale_coding_system
, 0);
6732 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6733 attrs
= Fcons (Fcons (Qppid
,
6734 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6736 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6738 attrs
= Fcons (Fcons (Qthcount
,
6739 make_fixnum_or_float (pe
.cntThreads
)),
6746 CloseHandle (h_snapshot
);
6755 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6757 /* If we were denied a handle to the process, try again after
6758 enabling the SeDebugPrivilege in our process. */
6761 TOKEN_PRIVILEGES priv_current
;
6763 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6765 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6767 restore_privilege (&priv_current
);
6773 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6776 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6777 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6779 buf
= xmalloc (blen
);
6780 result
= get_token_information (token
, TokenUser
,
6781 (LPVOID
)buf
, blen
, &needed
);
6784 memcpy (&user_token
, buf
, sizeof (user_token
));
6785 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6787 euid
= get_rid (user_token
.User
.Sid
);
6788 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6793 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6796 strcpy (uname
, "unknown");
6800 ulength
= strlen (uname
);
6806 /* Determine a reasonable euid and gid values. */
6807 if (xstrcasecmp ("administrator", uname
) == 0)
6809 euid
= 500; /* well-known Administrator uid */
6810 egid
= 513; /* well-known None gid */
6814 /* Get group id and name. */
6815 result
= get_token_information (token
, TokenPrimaryGroup
,
6816 (LPVOID
)buf
, blen
, &needed
);
6817 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6819 buf
= xrealloc (buf
, blen
= needed
);
6820 result
= get_token_information (token
, TokenPrimaryGroup
,
6821 (LPVOID
)buf
, blen
, &needed
);
6825 memcpy (&group_token
, buf
, sizeof (group_token
));
6826 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6828 egid
= get_rid (group_token
.PrimaryGroup
);
6829 dlength
= sizeof (domain
);
6831 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6832 gname
, &glength
, NULL
, &dlength
,
6835 w32_add_to_cache (group_token
.PrimaryGroup
,
6839 strcpy (gname
, "None");
6843 glength
= strlen (gname
);
6851 if (!is_windows_9x ())
6853 /* We couldn't open the process token, presumably because of
6854 insufficient access rights. Assume this process is run
6856 strcpy (uname
, "SYSTEM");
6857 strcpy (gname
, "None");
6858 euid
= 18; /* SYSTEM */
6859 egid
= 513; /* None */
6860 glength
= strlen (gname
);
6861 ulength
= strlen (uname
);
6863 /* If we are running under Windows 9X, where security calls are
6864 not supported, we assume all processes are run by the current
6866 else if (GetUserName (uname
, &ulength
))
6868 if (xstrcasecmp ("administrator", uname
) == 0)
6873 strcpy (gname
, "None");
6874 glength
= strlen (gname
);
6875 ulength
= strlen (uname
);
6881 strcpy (uname
, "administrator");
6882 ulength
= strlen (uname
);
6883 strcpy (gname
, "None");
6884 glength
= strlen (gname
);
6887 CloseHandle (token
);
6890 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6891 tem
= make_unibyte_string (uname
, ulength
);
6892 attrs
= Fcons (Fcons (Quser
,
6893 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6895 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6896 tem
= make_unibyte_string (gname
, glength
);
6897 attrs
= Fcons (Fcons (Qgroup
,
6898 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6901 if (global_memory_status_ex (&memstex
))
6902 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6903 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6905 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6906 double, so we need to do this for it... */
6908 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6909 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6910 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6912 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6914 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6915 else if (global_memory_status (&memst
))
6916 totphys
= memst
.dwTotalPhys
/ 1024.0;
6919 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6922 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6924 attrs
= Fcons (Fcons (Qmajflt
,
6925 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6927 attrs
= Fcons (Fcons (Qvsize
,
6928 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6930 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6932 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6935 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6937 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6939 attrs
= Fcons (Fcons (Qmajflt
,
6940 make_fixnum_or_float (mem
.PageFaultCount
)),
6942 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6944 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6947 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6949 DWORD rss
= maxrss
/ 1024;
6951 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6953 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6956 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6958 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6959 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6960 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6961 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6962 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6963 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6966 /* FIXME: Retrieve command line by walking the PEB of the process. */
6969 CloseHandle (h_proc
);
6975 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
6976 unsigned long long *totalswap
, unsigned long long *freeswap
)
6979 MEMORY_STATUS_EX memstex
;
6981 /* Use GlobalMemoryStatusEx if available, as it can report more than
6983 if (global_memory_status_ex (&memstex
))
6985 *totalram
= memstex
.ullTotalPhys
;
6986 *freeram
= memstex
.ullAvailPhys
;
6987 *totalswap
= memstex
.ullTotalPageFile
;
6988 *freeswap
= memstex
.ullAvailPageFile
;
6991 else if (global_memory_status (&memst
))
6993 *totalram
= memst
.dwTotalPhys
;
6994 *freeram
= memst
.dwAvailPhys
;
6995 *totalswap
= memst
.dwTotalPageFile
;
6996 *freeswap
= memst
.dwAvailPageFile
;
7004 /* Wrappers for winsock functions to map between our file descriptors
7005 and winsock's handles; also set h_errno for convenience.
7007 To allow Emacs to run on systems which don't have winsock support
7008 installed, we dynamically link to winsock on startup if present, and
7009 otherwise provide the minimum necessary functionality
7010 (eg. gethostname). */
7012 /* function pointers for relevant socket functions */
7013 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7014 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7015 int (PASCAL
*pfn_WSAGetLastError
) (void);
7016 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7017 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7018 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7019 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7020 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7021 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7022 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7023 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7024 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7025 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7026 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7027 int (PASCAL
*pfn_WSACleanup
) (void);
7029 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7030 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7031 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7032 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7033 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7034 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7035 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7036 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7037 const char * optval
, int optlen
);
7038 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7039 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7041 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7042 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7043 struct sockaddr
* from
, int * fromlen
);
7044 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7045 const struct sockaddr
* to
, int tolen
);
7047 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7048 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7049 #ifndef HANDLE_FLAG_INHERIT
7050 #define HANDLE_FLAG_INHERIT 1
7054 static int winsock_inuse
;
7059 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7061 release_listen_threads ();
7062 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7063 after WSAStartup returns successfully, but it seems reasonable
7064 to allow unloading winsock anyway in that case. */
7065 if (pfn_WSACleanup () == 0 ||
7066 pfn_WSAGetLastError () == WSAENETDOWN
)
7068 if (FreeLibrary (winsock_lib
))
7077 init_winsock (int load_now
)
7079 WSADATA winsockData
;
7081 if (winsock_lib
!= NULL
)
7084 pfn_SetHandleInformation
7085 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7086 "SetHandleInformation");
7088 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7090 if (winsock_lib
!= NULL
)
7092 /* dynamically link to socket functions */
7094 #define LOAD_PROC(fn) \
7095 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7098 LOAD_PROC (WSAStartup
);
7099 LOAD_PROC (WSASetLastError
);
7100 LOAD_PROC (WSAGetLastError
);
7101 LOAD_PROC (WSAEventSelect
);
7102 LOAD_PROC (WSACreateEvent
);
7103 LOAD_PROC (WSACloseEvent
);
7106 LOAD_PROC (connect
);
7107 LOAD_PROC (ioctlsocket
);
7110 LOAD_PROC (closesocket
);
7111 LOAD_PROC (shutdown
);
7114 LOAD_PROC (inet_addr
);
7115 LOAD_PROC (gethostname
);
7116 LOAD_PROC (gethostbyname
);
7117 LOAD_PROC (getservbyname
);
7118 LOAD_PROC (getpeername
);
7119 LOAD_PROC (WSACleanup
);
7120 LOAD_PROC (setsockopt
);
7122 LOAD_PROC (getsockname
);
7124 LOAD_PROC (recvfrom
);
7128 /* specify version 1.1 of winsock */
7129 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7131 if (winsockData
.wVersion
!= 0x101)
7136 /* Report that winsock exists and is usable, but leave
7137 socket functions disabled. I am assuming that calling
7138 WSAStartup does not require any network interaction,
7139 and in particular does not cause or require a dial-up
7140 connection to be established. */
7143 FreeLibrary (winsock_lib
);
7151 FreeLibrary (winsock_lib
);
7161 /* Function to map winsock error codes to errno codes for those errno
7162 code defined in errno.h (errno values not defined by errno.h are
7163 already in nt/inc/sys/socket.h). */
7170 if (winsock_lib
== NULL
)
7173 wsa_err
= pfn_WSAGetLastError ();
7177 case WSAEACCES
: errno
= EACCES
; break;
7178 case WSAEBADF
: errno
= EBADF
; break;
7179 case WSAEFAULT
: errno
= EFAULT
; break;
7180 case WSAEINTR
: errno
= EINTR
; break;
7181 case WSAEINVAL
: errno
= EINVAL
; break;
7182 case WSAEMFILE
: errno
= EMFILE
; break;
7183 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7184 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7185 default: errno
= wsa_err
; break;
7193 if (winsock_lib
!= NULL
)
7194 pfn_WSASetLastError (0);
7197 /* Extend strerror to handle the winsock-specific error codes. */
7201 } _wsa_errlist
[] = {
7202 {WSAEINTR
, "Interrupted function call"},
7203 {WSAEBADF
, "Bad file descriptor"},
7204 {WSAEACCES
, "Permission denied"},
7205 {WSAEFAULT
, "Bad address"},
7206 {WSAEINVAL
, "Invalid argument"},
7207 {WSAEMFILE
, "Too many open files"},
7209 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7210 {WSAEINPROGRESS
, "Operation now in progress"},
7211 {WSAEALREADY
, "Operation already in progress"},
7212 {WSAENOTSOCK
, "Socket operation on non-socket"},
7213 {WSAEDESTADDRREQ
, "Destination address required"},
7214 {WSAEMSGSIZE
, "Message too long"},
7215 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7216 {WSAENOPROTOOPT
, "Bad protocol option"},
7217 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7218 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7219 {WSAEOPNOTSUPP
, "Operation not supported"},
7220 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7221 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7222 {WSAEADDRINUSE
, "Address already in use"},
7223 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7224 {WSAENETDOWN
, "Network is down"},
7225 {WSAENETUNREACH
, "Network is unreachable"},
7226 {WSAENETRESET
, "Network dropped connection on reset"},
7227 {WSAECONNABORTED
, "Software caused connection abort"},
7228 {WSAECONNRESET
, "Connection reset by peer"},
7229 {WSAENOBUFS
, "No buffer space available"},
7230 {WSAEISCONN
, "Socket is already connected"},
7231 {WSAENOTCONN
, "Socket is not connected"},
7232 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7233 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7234 {WSAETIMEDOUT
, "Connection timed out"},
7235 {WSAECONNREFUSED
, "Connection refused"},
7236 {WSAELOOP
, "Network loop"}, /* not sure */
7237 {WSAENAMETOOLONG
, "Name is too long"},
7238 {WSAEHOSTDOWN
, "Host is down"},
7239 {WSAEHOSTUNREACH
, "No route to host"},
7240 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7241 {WSAEPROCLIM
, "Too many processes"},
7242 {WSAEUSERS
, "Too many users"}, /* not sure */
7243 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7244 {WSAESTALE
, "Data is stale"}, /* not sure */
7245 {WSAEREMOTE
, "Remote error"}, /* not sure */
7247 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7248 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7249 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7250 {WSAEDISCON
, "Graceful shutdown in progress"},
7252 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7253 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7254 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7255 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7256 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7257 {WSASYSCALLFAILURE
, "System call failure"},
7258 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7259 {WSATYPE_NOT_FOUND
, "Class type not found"},
7260 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7261 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7262 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7265 {WSAHOST_NOT_FOUND
, "Host not found"},
7266 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7267 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7268 {WSANO_DATA
, "Valid name, no data record of requested type"},
7274 sys_strerror (int error_no
)
7277 static char unknown_msg
[40];
7279 if (error_no
>= 0 && error_no
< sys_nerr
)
7280 return sys_errlist
[error_no
];
7282 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7283 if (_wsa_errlist
[i
].errnum
== error_no
)
7284 return _wsa_errlist
[i
].msg
;
7286 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7290 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7291 but I believe the method of keeping the socket handle separate (and
7292 insuring it is not inheritable) is the correct one. */
7294 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7296 static int socket_to_fd (SOCKET s
);
7299 sys_socket (int af
, int type
, int protocol
)
7303 if (winsock_lib
== NULL
)
7306 return INVALID_SOCKET
;
7311 /* call the real socket function */
7312 s
= pfn_socket (af
, type
, protocol
);
7314 if (s
!= INVALID_SOCKET
)
7315 return socket_to_fd (s
);
7321 /* Convert a SOCKET to a file descriptor. */
7323 socket_to_fd (SOCKET s
)
7328 /* Although under NT 3.5 _open_osfhandle will accept a socket
7329 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7330 that does not work under NT 3.1. However, we can get the same
7331 effect by using a backdoor function to replace an existing
7332 descriptor handle with the one we want. */
7334 /* allocate a file descriptor (with appropriate flags) */
7335 fd
= _open ("NUL:", _O_RDWR
);
7338 /* Make a non-inheritable copy of the socket handle. Note
7339 that it is possible that sockets aren't actually kernel
7340 handles, which appears to be the case on Windows 9x when
7341 the MS Proxy winsock client is installed. */
7343 /* Apparently there is a bug in NT 3.51 with some service
7344 packs, which prevents using DuplicateHandle to make a
7345 socket handle non-inheritable (causes WSACleanup to
7346 hang). The work-around is to use SetHandleInformation
7347 instead if it is available and implemented. */
7348 if (pfn_SetHandleInformation
)
7350 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7354 HANDLE parent
= GetCurrentProcess ();
7355 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7357 if (DuplicateHandle (parent
,
7363 DUPLICATE_SAME_ACCESS
))
7365 /* It is possible that DuplicateHandle succeeds even
7366 though the socket wasn't really a kernel handle,
7367 because a real handle has the same value. So
7368 test whether the new handle really is a socket. */
7369 long nonblocking
= 0;
7370 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7372 pfn_closesocket (s
);
7377 CloseHandle (new_s
);
7382 eassert (fd
< MAXDESC
);
7383 fd_info
[fd
].hnd
= (HANDLE
) s
;
7385 /* set our own internal flags */
7386 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7392 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7394 /* attach child_process to fd_info */
7395 if (fd_info
[ fd
].cp
!= NULL
)
7397 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7401 fd_info
[ fd
].cp
= cp
;
7404 winsock_inuse
++; /* count open sockets */
7412 pfn_closesocket (s
);
7418 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7420 if (winsock_lib
== NULL
)
7423 return SOCKET_ERROR
;
7427 if (fd_info
[s
].flags
& FILE_SOCKET
)
7429 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7430 if (rc
== SOCKET_ERROR
)
7435 return SOCKET_ERROR
;
7439 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7441 if (winsock_lib
== NULL
)
7444 return SOCKET_ERROR
;
7448 if (fd_info
[s
].flags
& FILE_SOCKET
)
7450 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7451 if (rc
== SOCKET_ERROR
)
7456 return SOCKET_ERROR
;
7460 sys_htons (u_short hostshort
)
7462 return (winsock_lib
!= NULL
) ?
7463 pfn_htons (hostshort
) : hostshort
;
7467 sys_ntohs (u_short netshort
)
7469 return (winsock_lib
!= NULL
) ?
7470 pfn_ntohs (netshort
) : netshort
;
7474 sys_inet_addr (const char * cp
)
7476 return (winsock_lib
!= NULL
) ?
7477 pfn_inet_addr (cp
) : INADDR_NONE
;
7481 sys_gethostname (char * name
, int namelen
)
7483 if (winsock_lib
!= NULL
)
7488 retval
= pfn_gethostname (name
, namelen
);
7489 if (retval
== SOCKET_ERROR
)
7494 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7495 return !GetComputerName (name
, (DWORD
*)&namelen
);
7498 return SOCKET_ERROR
;
7502 sys_gethostbyname (const char * name
)
7504 struct hostent
* host
;
7505 int h_err
= h_errno
;
7507 if (winsock_lib
== NULL
)
7509 h_errno
= NO_RECOVERY
;
7515 host
= pfn_gethostbyname (name
);
7527 sys_getservbyname (const char * name
, const char * proto
)
7529 struct servent
* serv
;
7531 if (winsock_lib
== NULL
)
7538 serv
= pfn_getservbyname (name
, proto
);
7545 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7547 if (winsock_lib
== NULL
)
7550 return SOCKET_ERROR
;
7554 if (fd_info
[s
].flags
& FILE_SOCKET
)
7556 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7557 if (rc
== SOCKET_ERROR
)
7562 return SOCKET_ERROR
;
7566 sys_shutdown (int s
, int how
)
7568 if (winsock_lib
== NULL
)
7571 return SOCKET_ERROR
;
7575 if (fd_info
[s
].flags
& FILE_SOCKET
)
7577 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7578 if (rc
== SOCKET_ERROR
)
7583 return SOCKET_ERROR
;
7587 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7589 if (winsock_lib
== NULL
)
7592 return SOCKET_ERROR
;
7596 if (fd_info
[s
].flags
& FILE_SOCKET
)
7598 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7599 (const char *)optval
, optlen
);
7600 if (rc
== SOCKET_ERROR
)
7605 return SOCKET_ERROR
;
7609 sys_listen (int s
, int backlog
)
7611 if (winsock_lib
== NULL
)
7614 return SOCKET_ERROR
;
7618 if (fd_info
[s
].flags
& FILE_SOCKET
)
7620 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7621 if (rc
== SOCKET_ERROR
)
7624 fd_info
[s
].flags
|= FILE_LISTEN
;
7628 return SOCKET_ERROR
;
7632 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7634 if (winsock_lib
== NULL
)
7637 return SOCKET_ERROR
;
7641 if (fd_info
[s
].flags
& FILE_SOCKET
)
7643 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7644 if (rc
== SOCKET_ERROR
)
7649 return SOCKET_ERROR
;
7653 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7655 if (winsock_lib
== NULL
)
7662 if (fd_info
[s
].flags
& FILE_LISTEN
)
7664 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7666 if (t
== INVALID_SOCKET
)
7669 fd
= socket_to_fd (t
);
7673 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7674 ResetEvent (fd_info
[s
].cp
->char_avail
);
7683 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7684 struct sockaddr
* from
, int * fromlen
)
7686 if (winsock_lib
== NULL
)
7689 return SOCKET_ERROR
;
7693 if (fd_info
[s
].flags
& FILE_SOCKET
)
7695 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7696 if (rc
== SOCKET_ERROR
)
7701 return SOCKET_ERROR
;
7705 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7706 const struct sockaddr
* to
, int tolen
)
7708 if (winsock_lib
== NULL
)
7711 return SOCKET_ERROR
;
7715 if (fd_info
[s
].flags
& FILE_SOCKET
)
7717 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7718 if (rc
== SOCKET_ERROR
)
7723 return SOCKET_ERROR
;
7726 /* Windows does not have an fcntl function. Provide an implementation
7727 good enough for Emacs. */
7729 fcntl (int s
, int cmd
, int options
)
7731 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7732 invoked in a context where fd1 is closed and all descriptors less
7733 than fd1 are open, so sys_dup is an adequate implementation. */
7734 if (cmd
== F_DUPFD_CLOEXEC
)
7738 if (fd_info
[s
].flags
& FILE_SOCKET
)
7740 if (winsock_lib
== NULL
)
7746 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7748 unsigned long nblock
= 1;
7749 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7750 if (rc
== SOCKET_ERROR
)
7752 /* Keep track of the fact that we set this to non-blocking. */
7753 fd_info
[s
].flags
|= FILE_NDELAY
;
7759 return SOCKET_ERROR
;
7762 else if ((fd_info
[s
].flags
& (FILE_PIPE
| FILE_WRITE
))
7763 == (FILE_PIPE
| FILE_WRITE
))
7765 /* Force our writes to pipes be non-blocking. */
7766 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7768 HANDLE h
= (HANDLE
)_get_osfhandle (s
);
7769 DWORD pipe_mode
= PIPE_NOWAIT
;
7771 if (!SetNamedPipeHandleState (h
, &pipe_mode
, NULL
, NULL
))
7773 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
7774 return SOCKET_ERROR
;
7776 fd_info
[s
].flags
|= FILE_NDELAY
;
7782 return SOCKET_ERROR
;
7786 return SOCKET_ERROR
;
7790 /* Shadow main io functions: we need to handle pipes and sockets more
7804 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7806 child_process
* cp
= fd_info
[fd
].cp
;
7808 fd_info
[fd
].cp
= NULL
;
7810 if (CHILD_ACTIVE (cp
))
7812 /* if last descriptor to active child_process then cleanup */
7814 for (i
= 0; i
< MAXDESC
; i
++)
7818 if (fd_info
[i
].cp
== cp
)
7823 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7825 if (winsock_lib
== NULL
) emacs_abort ();
7827 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7828 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7830 winsock_inuse
--; /* count open sockets */
7832 /* If the process handle is NULL, it's either a socket
7833 or serial connection, or a subprocess that was
7834 already reaped by reap_subprocess, but whose
7835 resources were not yet freed, because its output was
7836 not fully read yet by the time it was reaped. (This
7837 usually happens with async subprocesses whose output
7838 is being read by Emacs.) Otherwise, this process was
7839 not reaped yet, so we set its FD to a negative value
7840 to make sure sys_select will eventually get to
7841 calling the SIGCHLD handler for it, which will then
7842 invoke waitpid and reap_subprocess. */
7843 if (cp
->procinfo
.hProcess
== NULL
)
7851 if (fd
>= 0 && fd
< MAXDESC
)
7852 fd_info
[fd
].flags
= 0;
7854 /* Note that sockets do not need special treatment here (at least on
7855 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7856 closesocket is equivalent to CloseHandle, which is to be expected
7857 because socket handles are fully fledged kernel handles. */
7869 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7871 /* duplicate our internal info as well */
7872 fd_info
[new_fd
] = fd_info
[fd
];
7878 sys_dup2 (int src
, int dst
)
7882 if (dst
< 0 || dst
>= MAXDESC
)
7888 /* make sure we close the destination first if it's a pipe or socket */
7889 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7892 rc
= _dup2 (src
, dst
);
7895 /* duplicate our internal info as well */
7896 fd_info
[dst
] = fd_info
[src
];
7902 pipe2 (int * phandles
, int pipe2_flags
)
7907 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
7909 /* make pipe handles non-inheritable; when we spawn a child, we
7910 replace the relevant handle with an inheritable one. Also put
7911 pipes into binary mode; we will do text mode translation ourselves
7913 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7917 /* Protect against overflow, since Windows can open more handles than
7918 our fd_info array has room for. */
7919 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7921 _close (phandles
[0]);
7922 _close (phandles
[1]);
7928 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7929 fd_info
[phandles
[0]].flags
= flags
;
7931 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7932 fd_info
[phandles
[1]].flags
= flags
;
7939 /* Function to do blocking read of one byte, needed to implement
7940 select. It is only allowed on communication ports, sockets, or
7943 _sys_read_ahead (int fd
)
7948 if (fd
< 0 || fd
>= MAXDESC
)
7949 return STATUS_READ_ERROR
;
7951 cp
= fd_info
[fd
].cp
;
7953 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7954 return STATUS_READ_ERROR
;
7956 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7957 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7959 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7963 cp
->status
= STATUS_READ_IN_PROGRESS
;
7965 if (fd_info
[fd
].flags
& FILE_PIPE
)
7967 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7969 /* Give subprocess time to buffer some more output for us before
7970 reporting that input is available; we need this because Windows 95
7971 connects DOS programs to pipes by making the pipe appear to be
7972 the normal console stdout - as a result most DOS programs will
7973 write to stdout without buffering, ie. one character at a
7974 time. Even some W32 programs do this - "dir" in a command
7975 shell on NT is very slow if we don't do this. */
7978 int wait
= w32_pipe_read_delay
;
7984 /* Yield remainder of our time slice, effectively giving a
7985 temporary priority boost to the child process. */
7989 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7991 HANDLE hnd
= fd_info
[fd
].hnd
;
7992 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7995 /* Configure timeouts for blocking read. */
7996 if (!GetCommTimeouts (hnd
, &ct
))
7998 cp
->status
= STATUS_READ_ERROR
;
7999 return STATUS_READ_ERROR
;
8001 ct
.ReadIntervalTimeout
= 0;
8002 ct
.ReadTotalTimeoutMultiplier
= 0;
8003 ct
.ReadTotalTimeoutConstant
= 0;
8004 if (!SetCommTimeouts (hnd
, &ct
))
8006 cp
->status
= STATUS_READ_ERROR
;
8007 return STATUS_READ_ERROR
;
8010 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
8012 if (GetLastError () != ERROR_IO_PENDING
)
8014 cp
->status
= STATUS_READ_ERROR
;
8015 return STATUS_READ_ERROR
;
8017 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8019 cp
->status
= STATUS_READ_ERROR
;
8020 return STATUS_READ_ERROR
;
8024 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
8026 unsigned long nblock
= 0;
8027 /* We always want this to block, so temporarily disable NDELAY. */
8028 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8029 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8031 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
8033 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8036 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8040 if (rc
== sizeof (char))
8041 cp
->status
= STATUS_READ_SUCCEEDED
;
8043 cp
->status
= STATUS_READ_FAILED
;
8049 _sys_wait_accept (int fd
)
8055 if (fd
< 0 || fd
>= MAXDESC
)
8056 return STATUS_READ_ERROR
;
8058 cp
= fd_info
[fd
].cp
;
8060 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8061 return STATUS_READ_ERROR
;
8063 cp
->status
= STATUS_READ_FAILED
;
8065 hEv
= pfn_WSACreateEvent ();
8066 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8067 if (rc
!= SOCKET_ERROR
)
8070 rc
= WaitForSingleObject (hEv
, 500);
8072 } while (rc
== WAIT_TIMEOUT
8073 && cp
->status
!= STATUS_READ_ERROR
8075 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8076 if (rc
== WAIT_OBJECT_0
)
8077 cp
->status
= STATUS_READ_SUCCEEDED
;
8079 pfn_WSACloseEvent (hEv
);
8085 sys_read (int fd
, char * buffer
, unsigned int count
)
8090 char * orig_buffer
= buffer
;
8098 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8100 child_process
*cp
= fd_info
[fd
].cp
;
8102 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8110 /* re-read CR carried over from last read */
8111 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8113 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8117 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8120 /* presence of a child_process structure means we are operating in
8121 non-blocking mode - otherwise we just call _read directly.
8122 Note that the child_process structure might be missing because
8123 reap_subprocess has been called; in this case the pipe is
8124 already broken, so calling _read on it is okay. */
8127 int current_status
= cp
->status
;
8129 switch (current_status
)
8131 case STATUS_READ_FAILED
:
8132 case STATUS_READ_ERROR
:
8133 /* report normal EOF if nothing in buffer */
8135 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8138 case STATUS_READ_READY
:
8139 case STATUS_READ_IN_PROGRESS
:
8140 DebPrint (("sys_read called when read is in progress\n"));
8141 errno
= EWOULDBLOCK
;
8144 case STATUS_READ_SUCCEEDED
:
8145 /* consume read-ahead char */
8146 *buffer
++ = cp
->chr
;
8149 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8150 ResetEvent (cp
->char_avail
);
8152 case STATUS_READ_ACKNOWLEDGED
:
8156 DebPrint (("sys_read: bad status %d\n", current_status
));
8161 if (fd_info
[fd
].flags
& FILE_PIPE
)
8163 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8164 to_read
= min (waiting
, (DWORD
) count
);
8167 nchars
+= _read (fd
, buffer
, to_read
);
8169 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8171 HANDLE hnd
= fd_info
[fd
].hnd
;
8172 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8178 /* Configure timeouts for non-blocking read. */
8179 if (!GetCommTimeouts (hnd
, &ct
))
8184 ct
.ReadIntervalTimeout
= MAXDWORD
;
8185 ct
.ReadTotalTimeoutMultiplier
= 0;
8186 ct
.ReadTotalTimeoutConstant
= 0;
8187 if (!SetCommTimeouts (hnd
, &ct
))
8193 if (!ResetEvent (ovl
->hEvent
))
8198 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8200 if (GetLastError () != ERROR_IO_PENDING
)
8205 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8214 else /* FILE_SOCKET */
8216 if (winsock_lib
== NULL
) emacs_abort ();
8218 /* do the equivalent of a non-blocking read */
8219 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8220 if (waiting
== 0 && nchars
== 0)
8222 errno
= EWOULDBLOCK
;
8228 /* always use binary mode for sockets */
8229 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8230 if (res
== SOCKET_ERROR
)
8232 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8233 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8243 int nread
= _read (fd
, buffer
, count
);
8246 else if (nchars
== 0)
8251 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8252 /* Perform text mode translation if required. */
8253 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8255 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8256 /* If buffer contains only CR, return that. To be absolutely
8257 sure we should attempt to read the next char, but in
8258 practice a CR to be followed by LF would not appear by
8259 itself in the buffer. */
8260 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8262 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8268 nchars
= _read (fd
, buffer
, count
);
8273 /* From w32xfns.c */
8274 extern HANDLE interrupt_handle
;
8277 sys_write (int fd
, const void * buffer
, unsigned int count
)
8288 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8290 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8296 /* Perform text mode translation if required. */
8297 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8300 const unsigned char * src
= buffer
;
8301 unsigned char * dst
;
8304 SAFE_NALLOCA (tmpbuf
, 2, count
);
8309 unsigned char *next
;
8310 /* Copy next line or remaining bytes. */
8311 next
= _memccpy (dst
, src
, '\n', nbytes
);
8314 /* Copied one line ending with '\n'. */
8315 int copied
= next
- dst
;
8318 /* Insert '\r' before '\n'. */
8325 /* Copied remaining partial line -> now finished. */
8332 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8334 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8335 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8336 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8339 /* This is async (a.k.a. "overlapped") I/O, so the return value
8340 of FALSE from WriteFile means either an error or the output
8341 will be completed asynchronously (ERROR_IO_PENDING). */
8342 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8344 if (GetLastError () != ERROR_IO_PENDING
)
8351 /* Wait for the write to complete, and watch C-g while
8353 if (detect_input_pending ())
8354 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
,
8355 INFINITE
, QS_ALLINPUT
);
8357 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8361 /* User pressed C-g, cancel write, then leave.
8362 Don't bother cleaning up as we may only get stuck
8363 in buggy drivers. */
8364 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8366 errno
= EIO
; /* Why not EINTR? */
8369 case WAIT_OBJECT_0
+ 1:
8370 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8380 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8382 unsigned long nblock
= 0;
8383 if (winsock_lib
== NULL
) emacs_abort ();
8385 /* TODO: implement select() properly so non-blocking I/O works. */
8386 /* For now, make sure the write blocks. */
8387 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8388 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8390 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8392 /* Set the socket back to non-blocking if it was before,
8393 for other operations that support it. */
8394 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8397 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8400 if (nchars
== SOCKET_ERROR
)
8402 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8403 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8409 /* Some networked filesystems don't like too large writes, so
8410 break them into smaller chunks. See the Comments section of
8411 the MSDN documentation of WriteFile for details behind the
8412 choice of the value of CHUNK below. See also the thread
8413 http://thread.gmane.org/gmane.comp.version-control.git/145294
8414 in the git mailing list. */
8415 const unsigned char *p
= buffer
;
8416 const unsigned chunk
= 30 * 1024 * 1024;
8421 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8422 int n
= _write (fd
, p
, this_chunk
);
8427 /* When there's no buffer space in a pipe that is in the
8428 non-blocking mode, _write returns ENOSPC. We return
8429 EAGAIN instead, which should trigger the logic in
8430 send_process that enters waiting loop and calls
8431 wait_reading_process_output to allow process input to
8432 be accepted during the wait. Those calls to
8433 wait_reading_process_output allow sys_select to
8434 notice when process input becomes available, thus
8435 avoiding deadlock whereby each side of the pipe is
8436 blocked on write, waiting for the other party to read
8437 its end of the pipe. */
8440 && ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_NDELAY
))
8441 == (FILE_PIPE
| FILE_NDELAY
)))
8446 else if (n
< this_chunk
)
8458 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8460 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8462 /* Return information about network interface IFNAME, or about all
8463 interfaces (if IFNAME is nil). */
8465 network_interface_get_info (Lisp_Object ifname
)
8467 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8468 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8469 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8470 Lisp_Object res
= Qnil
;
8472 if (retval
== ERROR_BUFFER_OVERFLOW
)
8474 ainfo
= xrealloc (ainfo
, ainfo_len
);
8475 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8478 if (retval
== ERROR_SUCCESS
)
8480 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8481 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8483 struct sockaddr_in sa
;
8485 /* For the below, we need some winsock functions, so make sure
8486 the winsock DLL is loaded. If we cannot successfully load
8487 it, they will have no use of the information we provide,
8489 if (!winsock_lib
&& !init_winsock (1))
8492 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8494 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8496 /* Present Unix-compatible interface names, instead of the
8497 Windows names, which are really GUIDs not readable by
8499 static const char *ifmt
[] = {
8500 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8515 switch (adapter
->Type
)
8517 case MIB_IF_TYPE_ETHERNET
:
8518 /* Windows before Vista reports wireless adapters as
8519 Ethernet. Work around by looking at the Description
8521 if (strstr (adapter
->Description
, "Wireless "))
8524 if_num
= wlan_count
++;
8528 ifmt_idx
= ETHERNET
;
8529 if_num
= eth_count
++;
8532 case MIB_IF_TYPE_TOKENRING
:
8533 ifmt_idx
= TOKENRING
;
8534 if_num
= tr_count
++;
8536 case MIB_IF_TYPE_FDDI
:
8538 if_num
= fddi_count
++;
8540 case MIB_IF_TYPE_PPP
:
8542 if_num
= ppp_count
++;
8544 case MIB_IF_TYPE_SLIP
:
8546 if_num
= sl_count
++;
8548 case IF_TYPE_IEEE80211
:
8550 if_num
= wlan_count
++;
8552 case MIB_IF_TYPE_LOOPBACK
:
8555 ifmt_idx
= LOOPBACK
;
8556 if_num
= lo_count
++;
8562 ifmt_idx
= OTHER_IF
;
8563 if_num
= ifx_count
++;
8566 if (ifmt_idx
== NONE
)
8568 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8570 sa
.sin_family
= AF_INET
;
8571 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8572 if (ip_addr
== INADDR_NONE
)
8574 /* Bogus address, skip this interface. */
8577 sa
.sin_addr
.s_addr
= ip_addr
;
8580 res
= Fcons (Fcons (build_string (namebuf
),
8581 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8582 sizeof (struct sockaddr
))),
8584 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8586 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8587 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8588 Lisp_Object flags
= Qnil
;
8592 /* Flags. We guess most of them by type, since the
8593 Windows flags are different and hard to get by. */
8594 flags
= Fcons (intern ("up"), flags
);
8595 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8597 flags
= Fcons (intern ("broadcast"), flags
);
8598 flags
= Fcons (intern ("multicast"), flags
);
8600 flags
= Fcons (intern ("running"), flags
);
8601 if (ifmt_idx
== PPP
)
8603 flags
= Fcons (intern ("pointopoint"), flags
);
8604 flags
= Fcons (intern ("noarp"), flags
);
8606 if (adapter
->HaveWins
)
8607 flags
= Fcons (intern ("WINS"), flags
);
8608 if (adapter
->DhcpEnabled
)
8609 flags
= Fcons (intern ("dynamic"), flags
);
8611 res
= Fcons (flags
, res
);
8613 /* Hardware address and its family. */
8614 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8615 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8616 /* Windows does not support AF_LINK or AF_PACKET family
8617 of addresses. Use an arbitrary family number that is
8618 identical to what GNU/Linux returns. */
8619 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8622 sa
.sin_family
= AF_INET
;
8623 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8624 if (net_mask
!= INADDR_NONE
)
8626 sa
.sin_addr
.s_addr
= net_mask
;
8628 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8629 sizeof (struct sockaddr
)),
8633 res
= Fcons (Qnil
, res
);
8635 sa
.sin_family
= AF_INET
;
8636 if (ip_addr
!= INADDR_NONE
)
8638 /* Broadcast address is only reported by
8639 GetAdaptersAddresses, which is of limited
8640 availability. Generate it on our own. */
8641 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8643 sa
.sin_addr
.s_addr
= bcast_addr
;
8645 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8646 sizeof (struct sockaddr
)),
8650 sa
.sin_addr
.s_addr
= ip_addr
;
8652 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8653 sizeof (struct sockaddr
)),
8657 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8660 /* GetAdaptersInfo is documented to not report loopback
8661 interfaces, so we generate one out of thin air. */
8664 sa
.sin_family
= AF_INET
;
8668 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8669 res
= Fcons (Fcons (build_string ("lo"),
8670 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8671 sizeof (struct sockaddr
))),
8674 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8676 res
= Fcons (Fcons (intern ("running"),
8677 Fcons (intern ("loopback"),
8678 Fcons (intern ("up"), Qnil
))), Qnil
);
8679 /* 772 is what 3 different GNU/Linux systems report for
8680 the loopback interface. */
8681 res
= Fcons (Fcons (make_number (772),
8682 Fmake_vector (make_number (6),
8685 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8686 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8687 sizeof (struct sockaddr
)),
8689 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8690 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8691 sizeof (struct sockaddr
)),
8693 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8694 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8695 sizeof (struct sockaddr
)),
8708 network_interface_list (void)
8710 return network_interface_get_info (Qnil
);
8714 network_interface_info (Lisp_Object ifname
)
8716 CHECK_STRING (ifname
);
8717 return network_interface_get_info (ifname
);
8721 /* The Windows CRT functions are "optimized for speed", so they don't
8722 check for timezone and DST changes if they were last called less
8723 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8724 all Emacs features that repeatedly call time functions (e.g.,
8725 display-time) are in real danger of missing timezone and DST
8726 changes. Calling tzset before each localtime call fixes that. */
8728 sys_localtime (const time_t *t
)
8731 return localtime (t
);
8736 /* Try loading LIBRARY_ID from the file(s) specified in
8737 Vdynamic_library_alist. If the library is loaded successfully,
8738 return the handle of the DLL, and record the filename in the
8739 property :loaded-from of LIBRARY_ID. If the library could not be
8740 found, or when it was already loaded (because the handle is not
8741 recorded anywhere, and so is lost after use), return NULL.
8743 We could also save the handle in :loaded-from, but currently
8744 there's no use case for it. */
8746 w32_delayed_load (Lisp_Object library_id
)
8748 HMODULE dll_handle
= NULL
;
8750 CHECK_SYMBOL (library_id
);
8752 if (CONSP (Vdynamic_library_alist
)
8753 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8755 Lisp_Object found
= Qnil
;
8756 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8759 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8761 Lisp_Object dll
= XCAR (dlls
);
8762 char name
[MAX_UTF8_PATH
];
8766 dll
= ENCODE_FILE (dll
);
8767 if (w32_unicode_filenames
)
8769 wchar_t name_w
[MAX_PATH
];
8771 filename_to_utf16 (SSDATA (dll
), name_w
);
8772 dll_handle
= LoadLibraryW (name_w
);
8775 res
= GetModuleFileNameW (dll_handle
, name_w
,
8778 filename_from_utf16 (name_w
, name
);
8783 char name_a
[MAX_PATH
];
8785 filename_to_ansi (SSDATA (dll
), name_a
);
8786 dll_handle
= LoadLibraryA (name_a
);
8789 res
= GetModuleFileNameA (dll_handle
, name_a
,
8792 filename_from_ansi (name_a
, name
);
8797 ptrdiff_t len
= strlen (name
);
8800 /* Possibly truncated */
8801 ? make_specified_string (name
, -1, len
, 1)
8803 /* This prevents thread start and end notifications
8804 from being sent to the DLL, for every thread we
8805 start. We don't need those notifications because
8806 threads we create never use any of these DLLs, only
8807 the main thread uses them. This is supposed to
8808 speed up thread creation. */
8809 DisableThreadLibraryCalls (dll_handle
);
8814 Fput (library_id
, QCloaded_from
, found
);
8822 check_windows_init_file (void)
8824 /* A common indication that Emacs is not installed properly is when
8825 it cannot find the Windows installation file. If this file does
8826 not exist in the expected place, tell the user. */
8828 if (!noninteractive
&& !inhibit_window_system
8829 /* Vload_path is not yet initialized when we are loading
8831 && NILP (Vpurify_flag
))
8833 Lisp_Object init_file
;
8836 /* Implementation note: this function runs early during Emacs
8837 startup, before startup.el is run. So Vload_path is still in
8838 its initial unibyte form, but it holds UTF-8 encoded file
8839 names, since init_callproc was already called. So we do not
8840 need to ENCODE_FILE here, but we do need to convert the file
8841 names from UTF-8 to ANSI. */
8842 init_file
= build_string ("term/w32-win");
8843 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
8846 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8847 char *init_file_name
= SDATA (init_file
);
8848 char *load_path
= SDATA (load_path_print
);
8849 char *buffer
= alloca (1024
8850 + strlen (init_file_name
)
8851 + strlen (load_path
));
8856 "The Emacs Windows initialization file \"%s.el\" "
8857 "could not be found in your Emacs installation. "
8858 "Emacs checked the following directories for this file:\n"
8860 "When Emacs cannot find this file, it usually means that it "
8861 "was not installed properly, or its distribution file was "
8862 "not unpacked properly.\nSee the README.W32 file in the "
8863 "top-level Emacs directory for more information.",
8864 init_file_name
, load_path
);
8865 needed
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8869 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8871 pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8873 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8874 NULL
, 0, NULL
, NULL
);
8877 char *msg_a
= alloca (needed
+ 1);
8879 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8886 "Emacs Abort Dialog",
8887 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8888 /* Use the low-level system abort. */
8899 term_ntproc (int ignored
)
8905 /* shutdown the socket interface if necessary */
8912 init_ntproc (int dumping
)
8914 sigset_t initial_mask
= 0;
8916 /* Initialize the socket interface now if available and requested by
8917 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8918 delayed until open-network-stream is called (w32-has-winsock can
8919 also be used to dynamically load or reload winsock).
8921 Conveniently, init_environment is called before us, so
8922 PRELOAD_WINSOCK can be set in the registry. */
8924 /* Always initialize this correctly. */
8927 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8928 init_winsock (TRUE
);
8930 /* Initial preparation for subprocess support: replace our standard
8931 handles with non-inheritable versions. */
8934 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8935 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8936 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8938 parent
= GetCurrentProcess ();
8940 /* ignore errors when duplicating and closing; typically the
8941 handles will be invalid when running as a gui program. */
8942 DuplicateHandle (parent
,
8943 GetStdHandle (STD_INPUT_HANDLE
),
8948 DUPLICATE_SAME_ACCESS
);
8950 DuplicateHandle (parent
,
8951 GetStdHandle (STD_OUTPUT_HANDLE
),
8956 DUPLICATE_SAME_ACCESS
);
8958 DuplicateHandle (parent
,
8959 GetStdHandle (STD_ERROR_HANDLE
),
8964 DUPLICATE_SAME_ACCESS
);
8970 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8971 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8973 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8976 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8977 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8979 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8982 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8983 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8985 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8989 /* unfortunately, atexit depends on implementation of malloc */
8990 /* atexit (term_ntproc); */
8993 /* Make sure we start with all signals unblocked. */
8994 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8995 signal (SIGABRT
, term_ntproc
);
8999 /* determine which drives are fixed, for GetCachedVolumeInformation */
9001 /* GetDriveType must have trailing backslash. */
9002 char drive
[] = "A:\\";
9004 /* Loop over all possible drive letters */
9005 while (*drive
<= 'Z')
9007 /* Record if this drive letter refers to a fixed drive. */
9008 fixed_drives
[DRIVE_INDEX (*drive
)] =
9009 (GetDriveType (drive
) == DRIVE_FIXED
);
9014 /* Reset the volume info cache. */
9015 volume_cache
= NULL
;
9020 shutdown_handler ensures that buffers' autosave files are
9021 up to date when the user logs off, or the system shuts down.
9024 shutdown_handler (DWORD type
)
9026 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
9027 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
9028 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
9029 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
9031 /* Shut down cleanly, making sure autosave files are up to date. */
9032 shut_down_emacs (0, Qnil
);
9035 /* Allow other handlers to handle this signal. */
9039 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
9040 NT, return a handle to GDI32.DLL. */
9042 maybe_load_unicows_dll (void)
9044 if (os_subtype
== OS_9X
)
9046 HANDLE ret
= LoadLibrary ("Unicows.dll");
9049 /* These two functions are present on Windows 9X as stubs
9050 that always fail. We need the real implementations from
9051 UNICOWS.DLL, so we must call these functions through
9052 pointers, and assign the correct addresses to these
9053 pointers at program startup (see emacs.c, which calls
9054 this function early on). */
9055 pMultiByteToWideChar
= GetProcAddress (ret
, "MultiByteToWideChar");
9056 pWideCharToMultiByte
= GetProcAddress (ret
, "WideCharToMultiByte");
9063 button
= MessageBox (NULL
,
9064 "Emacs cannot load the UNICOWS.DLL library.\n"
9065 "This library is essential for using Emacs\n"
9066 "on this system. You need to install it.\n\n"
9067 "Emacs will exit when you click OK.",
9068 "Emacs cannot load UNICOWS.DLL",
9069 MB_ICONERROR
| MB_TASKMODAL
9070 | MB_SETFOREGROUND
| MB_OK
);
9081 /* On NT family of Windows, these two functions are always
9082 linked in, so we just assign their addresses to the 2
9083 pointers; no need for the LoadLibrary dance. */
9084 pMultiByteToWideChar
= MultiByteToWideChar
;
9085 pWideCharToMultiByte
= WideCharToMultiByte
;
9086 return LoadLibrary ("Gdi32.dll");
9091 globals_of_w32 is used to initialize those global variables that
9092 must always be initialized on startup even when the global variable
9093 initialized is non zero (see the function main in emacs.c).
9096 globals_of_w32 (void)
9098 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9100 get_process_times_fn
= (GetProcessTimes_Proc
)
9101 GetProcAddress (kernel32
, "GetProcessTimes");
9103 DEFSYM (QCloaded_from
, ":loaded-from");
9105 g_b_init_is_windows_9x
= 0;
9106 g_b_init_open_process_token
= 0;
9107 g_b_init_get_token_information
= 0;
9108 g_b_init_lookup_account_sid
= 0;
9109 g_b_init_get_sid_sub_authority
= 0;
9110 g_b_init_get_sid_sub_authority_count
= 0;
9111 g_b_init_get_security_info
= 0;
9112 g_b_init_get_file_security_w
= 0;
9113 g_b_init_get_file_security_a
= 0;
9114 g_b_init_get_security_descriptor_owner
= 0;
9115 g_b_init_get_security_descriptor_group
= 0;
9116 g_b_init_is_valid_sid
= 0;
9117 g_b_init_create_toolhelp32_snapshot
= 0;
9118 g_b_init_process32_first
= 0;
9119 g_b_init_process32_next
= 0;
9120 g_b_init_open_thread_token
= 0;
9121 g_b_init_impersonate_self
= 0;
9122 g_b_init_revert_to_self
= 0;
9123 g_b_init_get_process_memory_info
= 0;
9124 g_b_init_get_process_working_set_size
= 0;
9125 g_b_init_global_memory_status
= 0;
9126 g_b_init_global_memory_status_ex
= 0;
9127 g_b_init_equal_sid
= 0;
9128 g_b_init_copy_sid
= 0;
9129 g_b_init_get_length_sid
= 0;
9130 g_b_init_get_native_system_info
= 0;
9131 g_b_init_get_system_times
= 0;
9132 g_b_init_create_symbolic_link_w
= 0;
9133 g_b_init_create_symbolic_link_a
= 0;
9134 g_b_init_get_security_descriptor_dacl
= 0;
9135 g_b_init_convert_sd_to_sddl
= 0;
9136 g_b_init_convert_sddl_to_sd
= 0;
9137 g_b_init_is_valid_security_descriptor
= 0;
9138 g_b_init_set_file_security_w
= 0;
9139 g_b_init_set_file_security_a
= 0;
9140 g_b_init_set_named_security_info_w
= 0;
9141 g_b_init_set_named_security_info_a
= 0;
9142 g_b_init_get_adapters_info
= 0;
9143 g_b_init_compare_string_w
= 0;
9144 num_of_processors
= 0;
9145 /* The following sets a handler for shutdown notifications for
9146 console apps. This actually applies to Emacs in both console and
9147 GUI modes, since we had to fool windows into thinking emacs is a
9148 console application to get console mode to work. */
9149 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9151 /* "None" is the default group name on standalone workstations. */
9152 strcpy (dflt_group_name
, "None");
9154 /* Reset, in case it has some value inherited from dump time. */
9155 w32_stat_get_owner_group
= 0;
9157 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9158 (a.k.a. "wide") APIs to invoke functions that accept file
9160 if (is_windows_9x ())
9161 w32_unicode_filenames
= 0;
9163 w32_unicode_filenames
= 1;
9166 /* For make-serial-process */
9168 serial_open (Lisp_Object port_obj
)
9170 char *port
= SSDATA (port_obj
);
9175 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9176 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9177 if (hnd
== INVALID_HANDLE_VALUE
)
9178 error ("Could not open %s", port
);
9179 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9181 error ("Could not open %s", port
);
9185 error ("Could not create child process");
9187 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9188 fd_info
[ fd
].hnd
= hnd
;
9189 fd_info
[ fd
].flags
|=
9190 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9191 if (fd_info
[ fd
].cp
!= NULL
)
9193 error ("fd_info[fd = %d] is already in use", fd
);
9195 fd_info
[ fd
].cp
= cp
;
9196 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9197 if (cp
->ovl_read
.hEvent
== NULL
)
9198 error ("Could not create read event");
9199 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9200 if (cp
->ovl_write
.hEvent
== NULL
)
9201 error ("Could not create write event");
9206 /* For serial-process-configure */
9208 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9210 Lisp_Object childp2
= Qnil
;
9211 Lisp_Object tem
= Qnil
;
9215 char summary
[4] = "???"; /* This usually becomes "8N1". */
9217 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9218 error ("Not a serial process");
9219 hnd
= fd_info
[ p
->outfd
].hnd
;
9221 childp2
= Fcopy_sequence (p
->childp
);
9223 /* Initialize timeouts for blocking read and blocking write. */
9224 if (!GetCommTimeouts (hnd
, &ct
))
9225 error ("GetCommTimeouts() failed");
9226 ct
.ReadIntervalTimeout
= 0;
9227 ct
.ReadTotalTimeoutMultiplier
= 0;
9228 ct
.ReadTotalTimeoutConstant
= 0;
9229 ct
.WriteTotalTimeoutMultiplier
= 0;
9230 ct
.WriteTotalTimeoutConstant
= 0;
9231 if (!SetCommTimeouts (hnd
, &ct
))
9232 error ("SetCommTimeouts() failed");
9233 /* Read port attributes and prepare default configuration. */
9234 memset (&dcb
, 0, sizeof (dcb
));
9235 dcb
.DCBlength
= sizeof (DCB
);
9236 if (!GetCommState (hnd
, &dcb
))
9237 error ("GetCommState() failed");
9240 dcb
.fAbortOnError
= FALSE
;
9241 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9246 /* Configure speed. */
9247 if (!NILP (Fplist_member (contact
, QCspeed
)))
9248 tem
= Fplist_get (contact
, QCspeed
);
9250 tem
= Fplist_get (p
->childp
, QCspeed
);
9252 dcb
.BaudRate
= XINT (tem
);
9253 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9255 /* Configure bytesize. */
9256 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9257 tem
= Fplist_get (contact
, QCbytesize
);
9259 tem
= Fplist_get (p
->childp
, QCbytesize
);
9261 tem
= make_number (8);
9263 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9264 error (":bytesize must be nil (8), 7, or 8");
9265 dcb
.ByteSize
= XINT (tem
);
9266 summary
[0] = XINT (tem
) + '0';
9267 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9269 /* Configure parity. */
9270 if (!NILP (Fplist_member (contact
, QCparity
)))
9271 tem
= Fplist_get (contact
, QCparity
);
9273 tem
= Fplist_get (p
->childp
, QCparity
);
9274 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9275 error (":parity must be nil (no parity), `even', or `odd'");
9276 dcb
.fParity
= FALSE
;
9277 dcb
.Parity
= NOPARITY
;
9278 dcb
.fErrorChar
= FALSE
;
9283 else if (EQ (tem
, Qeven
))
9287 dcb
.Parity
= EVENPARITY
;
9288 dcb
.fErrorChar
= TRUE
;
9290 else if (EQ (tem
, Qodd
))
9294 dcb
.Parity
= ODDPARITY
;
9295 dcb
.fErrorChar
= TRUE
;
9297 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9299 /* Configure stopbits. */
9300 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9301 tem
= Fplist_get (contact
, QCstopbits
);
9303 tem
= Fplist_get (p
->childp
, QCstopbits
);
9305 tem
= make_number (1);
9307 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9308 error (":stopbits must be nil (1 stopbit), 1, or 2");
9309 summary
[2] = XINT (tem
) + '0';
9310 if (XINT (tem
) == 1)
9311 dcb
.StopBits
= ONESTOPBIT
;
9312 else if (XINT (tem
) == 2)
9313 dcb
.StopBits
= TWOSTOPBITS
;
9314 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9316 /* Configure flowcontrol. */
9317 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9318 tem
= Fplist_get (contact
, QCflowcontrol
);
9320 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9321 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9322 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9323 dcb
.fOutxCtsFlow
= FALSE
;
9324 dcb
.fOutxDsrFlow
= FALSE
;
9325 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9326 dcb
.fDsrSensitivity
= FALSE
;
9327 dcb
.fTXContinueOnXoff
= FALSE
;
9330 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9331 dcb
.XonChar
= 17; /* Control-Q */
9332 dcb
.XoffChar
= 19; /* Control-S */
9335 /* Already configured. */
9337 else if (EQ (tem
, Qhw
))
9339 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9340 dcb
.fOutxCtsFlow
= TRUE
;
9342 else if (EQ (tem
, Qsw
))
9347 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9349 /* Activate configuration. */
9350 if (!SetCommState (hnd
, &dcb
))
9351 error ("SetCommState() failed");
9353 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9354 pset_childp (p
, childp2
);
9360 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9363 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9364 int fd
= process
->infd
;
9366 n
= sys_read (fd
, (char*)buf
, sz
);
9373 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9374 if (err
== EWOULDBLOCK
)
9377 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9383 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9385 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9386 int fd
= process
->outfd
;
9387 ssize_t n
= sys_write (fd
, buf
, sz
);
9389 /* 0 or more bytes written means everything went fine. */
9393 /* Negative bytes written means we got an error in errno.
9394 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9395 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9396 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9400 #endif /* HAVE_GNUTLS */