1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2014 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 (_W64) 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(_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 Lisp_Object QCloaded_from
;
247 void globals_of_w32 (void);
248 static DWORD
get_rid (PSID
);
249 static int is_symlink (const char *);
250 static char * chase_symlinks (const char *);
251 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
252 static int restore_privilege (TOKEN_PRIVILEGES
*);
253 static BOOL WINAPI
revert_to_self (void);
255 static int sys_access (const char *, int);
256 extern void *e_malloc (size_t);
257 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
258 struct timespec
*, void *);
259 extern int sys_dup (int);
264 /* Initialization states.
266 WARNING: If you add any more such variables for additional APIs,
267 you MUST add initialization for them to globals_of_w32
268 below. This is because these variables might get set
269 to non-NULL values during dumping, but the dumped Emacs
270 cannot reuse those values, because it could be run on a
271 different version of the OS, where API addresses are
273 static BOOL g_b_init_is_windows_9x
;
274 static BOOL g_b_init_open_process_token
;
275 static BOOL g_b_init_get_token_information
;
276 static BOOL g_b_init_lookup_account_sid
;
277 static BOOL g_b_init_get_sid_sub_authority
;
278 static BOOL g_b_init_get_sid_sub_authority_count
;
279 static BOOL g_b_init_get_security_info
;
280 static BOOL g_b_init_get_file_security_w
;
281 static BOOL g_b_init_get_file_security_a
;
282 static BOOL g_b_init_get_security_descriptor_owner
;
283 static BOOL g_b_init_get_security_descriptor_group
;
284 static BOOL g_b_init_is_valid_sid
;
285 static BOOL g_b_init_create_toolhelp32_snapshot
;
286 static BOOL g_b_init_process32_first
;
287 static BOOL g_b_init_process32_next
;
288 static BOOL g_b_init_open_thread_token
;
289 static BOOL g_b_init_impersonate_self
;
290 static BOOL g_b_init_revert_to_self
;
291 static BOOL g_b_init_get_process_memory_info
;
292 static BOOL g_b_init_get_process_working_set_size
;
293 static BOOL g_b_init_global_memory_status
;
294 static BOOL g_b_init_global_memory_status_ex
;
295 static BOOL g_b_init_get_length_sid
;
296 static BOOL g_b_init_equal_sid
;
297 static BOOL g_b_init_copy_sid
;
298 static BOOL g_b_init_get_native_system_info
;
299 static BOOL g_b_init_get_system_times
;
300 static BOOL g_b_init_create_symbolic_link_w
;
301 static BOOL g_b_init_create_symbolic_link_a
;
302 static BOOL g_b_init_get_security_descriptor_dacl
;
303 static BOOL g_b_init_convert_sd_to_sddl
;
304 static BOOL g_b_init_convert_sddl_to_sd
;
305 static BOOL g_b_init_is_valid_security_descriptor
;
306 static BOOL g_b_init_set_file_security_w
;
307 static BOOL g_b_init_set_file_security_a
;
308 static BOOL g_b_init_set_named_security_info_w
;
309 static BOOL g_b_init_set_named_security_info_a
;
310 static BOOL g_b_init_get_adapters_info
;
312 BOOL g_b_init_compare_string_w
;
315 BEGIN: Wrapper functions around OpenProcessToken
316 and other functions in advapi32.dll that are only
317 supported in Windows NT / 2k / XP
319 /* ** Function pointer typedefs ** */
320 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
321 HANDLE ProcessHandle
,
323 PHANDLE TokenHandle
);
324 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
326 TOKEN_INFORMATION_CLASS TokenInformationClass
,
327 LPVOID TokenInformation
,
328 DWORD TokenInformationLength
,
329 PDWORD ReturnLength
);
330 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
331 HANDLE process_handle
,
332 LPFILETIME creation_time
,
333 LPFILETIME exit_time
,
334 LPFILETIME kernel_time
,
335 LPFILETIME user_time
);
337 GetProcessTimes_Proc get_process_times_fn
= NULL
;
340 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
342 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
344 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
345 LPCTSTR lpSystemName
,
350 LPDWORD cbDomainName
,
351 PSID_NAME_USE peUse
);
352 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
355 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
357 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
359 SE_OBJECT_TYPE ObjectType
,
360 SECURITY_INFORMATION SecurityInfo
,
365 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
366 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
368 SECURITY_INFORMATION RequestedInformation
,
369 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
371 LPDWORD lpnLengthNeeded
);
372 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
374 SECURITY_INFORMATION RequestedInformation
,
375 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
377 LPDWORD lpnLengthNeeded
);
378 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
380 SECURITY_INFORMATION SecurityInformation
,
381 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
382 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
384 SECURITY_INFORMATION SecurityInformation
,
385 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
386 typedef DWORD (WINAPI
*SetNamedSecurityInfoW_Proc
) (
387 LPCWSTR lpObjectName
,
388 SE_OBJECT_TYPE ObjectType
,
389 SECURITY_INFORMATION SecurityInformation
,
394 typedef DWORD (WINAPI
*SetNamedSecurityInfoA_Proc
) (
396 SE_OBJECT_TYPE ObjectType
,
397 SECURITY_INFORMATION SecurityInformation
,
402 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
403 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
405 LPBOOL lpbOwnerDefaulted
);
406 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
407 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
409 LPBOOL lpbGroupDefaulted
);
410 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
411 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
412 LPBOOL lpbDaclPresent
,
414 LPBOOL lpbDaclDefaulted
);
415 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
417 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
419 DWORD th32ProcessID
);
420 typedef BOOL (WINAPI
* Process32First_Proc
) (
422 LPPROCESSENTRY32 lppe
);
423 typedef BOOL (WINAPI
* Process32Next_Proc
) (
425 LPPROCESSENTRY32 lppe
);
426 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
430 PHANDLE TokenHandle
);
431 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
432 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
433 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
434 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
436 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
438 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
440 PSIZE_T lpMinimumWorkingSetSize
,
441 PSIZE_T lpMaximumWorkingSetSize
);
442 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
443 LPMEMORYSTATUS lpBuffer
);
444 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
445 LPMEMORY_STATUS_EX lpBuffer
);
446 typedef BOOL (WINAPI
* CopySid_Proc
) (
447 DWORD nDestinationSidLength
,
448 PSID pDestinationSid
,
450 typedef BOOL (WINAPI
* EqualSid_Proc
) (
453 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
455 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
456 LPSYSTEM_INFO lpSystemInfo
);
457 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
458 LPFILETIME lpIdleTime
,
459 LPFILETIME lpKernelTime
,
460 LPFILETIME lpUserTime
);
461 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
462 LPCWSTR lpSymlinkFileName
,
463 LPCWSTR lpTargetFileName
,
465 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
466 LPCSTR lpSymlinkFileName
,
467 LPCSTR lpTargetFileName
,
469 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
470 LPCTSTR StringSecurityDescriptor
,
471 DWORD StringSDRevision
,
472 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
473 PULONG SecurityDescriptorSize
);
474 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
475 PSECURITY_DESCRIPTOR SecurityDescriptor
,
476 DWORD RequestedStringSDRevision
,
477 SECURITY_INFORMATION SecurityInformation
,
478 LPTSTR
*StringSecurityDescriptor
,
479 PULONG StringSecurityDescriptorLen
);
480 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
481 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
482 PIP_ADAPTER_INFO pAdapterInfo
,
485 int (WINAPI
*pMultiByteToWideChar
)(UINT
,DWORD
,LPCSTR
,int,LPWSTR
,int);
486 int (WINAPI
*pWideCharToMultiByte
)(UINT
,DWORD
,LPCWSTR
,int,LPSTR
,int,LPCSTR
,LPBOOL
);
488 /* ** A utility function ** */
492 static BOOL s_b_ret
= 0;
493 OSVERSIONINFO os_ver
;
494 if (g_b_init_is_windows_9x
== 0)
496 g_b_init_is_windows_9x
= 1;
497 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
498 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
499 if (GetVersionEx (&os_ver
))
501 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
507 static Lisp_Object
ltime (ULONGLONG
);
509 /* Get total user and system times for get-internal-run-time.
510 Returns a list of integers if the times are provided by the OS
511 (NT derivatives), otherwise it returns the result of current-time. */
513 w32_get_internal_run_time (void)
515 if (get_process_times_fn
)
517 FILETIME create
, exit
, kernel
, user
;
518 HANDLE proc
= GetCurrentProcess ();
519 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
521 LARGE_INTEGER user_int
, kernel_int
, total
;
522 user_int
.LowPart
= user
.dwLowDateTime
;
523 user_int
.HighPart
= user
.dwHighDateTime
;
524 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
525 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
526 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
527 return ltime (total
.QuadPart
);
531 return Fcurrent_time ();
534 /* ** The wrapper functions ** */
537 open_process_token (HANDLE ProcessHandle
,
541 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
542 HMODULE hm_advapi32
= NULL
;
543 if (is_windows_9x () == TRUE
)
547 if (g_b_init_open_process_token
== 0)
549 g_b_init_open_process_token
= 1;
550 hm_advapi32
= LoadLibrary ("Advapi32.dll");
551 s_pfn_Open_Process_Token
=
552 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
554 if (s_pfn_Open_Process_Token
== NULL
)
559 s_pfn_Open_Process_Token (
567 get_token_information (HANDLE TokenHandle
,
568 TOKEN_INFORMATION_CLASS TokenInformationClass
,
569 LPVOID TokenInformation
,
570 DWORD TokenInformationLength
,
573 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
574 HMODULE hm_advapi32
= NULL
;
575 if (is_windows_9x () == TRUE
)
579 if (g_b_init_get_token_information
== 0)
581 g_b_init_get_token_information
= 1;
582 hm_advapi32
= LoadLibrary ("Advapi32.dll");
583 s_pfn_Get_Token_Information
=
584 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
586 if (s_pfn_Get_Token_Information
== NULL
)
591 s_pfn_Get_Token_Information (
593 TokenInformationClass
,
595 TokenInformationLength
,
601 lookup_account_sid (LPCTSTR lpSystemName
,
606 LPDWORD cbDomainName
,
609 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
610 HMODULE hm_advapi32
= NULL
;
611 if (is_windows_9x () == TRUE
)
615 if (g_b_init_lookup_account_sid
== 0)
617 g_b_init_lookup_account_sid
= 1;
618 hm_advapi32
= LoadLibrary ("Advapi32.dll");
619 s_pfn_Lookup_Account_Sid
=
620 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
622 if (s_pfn_Lookup_Account_Sid
== NULL
)
627 s_pfn_Lookup_Account_Sid (
639 get_sid_sub_authority (PSID pSid
, DWORD n
)
641 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
642 static DWORD zero
= 0U;
643 HMODULE hm_advapi32
= NULL
;
644 if (is_windows_9x () == TRUE
)
648 if (g_b_init_get_sid_sub_authority
== 0)
650 g_b_init_get_sid_sub_authority
= 1;
651 hm_advapi32
= LoadLibrary ("Advapi32.dll");
652 s_pfn_Get_Sid_Sub_Authority
=
653 (GetSidSubAuthority_Proc
) GetProcAddress (
654 hm_advapi32
, "GetSidSubAuthority");
656 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
660 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
664 get_sid_sub_authority_count (PSID pSid
)
666 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
667 static UCHAR zero
= 0U;
668 HMODULE hm_advapi32
= NULL
;
669 if (is_windows_9x () == TRUE
)
673 if (g_b_init_get_sid_sub_authority_count
== 0)
675 g_b_init_get_sid_sub_authority_count
= 1;
676 hm_advapi32
= LoadLibrary ("Advapi32.dll");
677 s_pfn_Get_Sid_Sub_Authority_Count
=
678 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
679 hm_advapi32
, "GetSidSubAuthorityCount");
681 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
685 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
689 get_security_info (HANDLE handle
,
690 SE_OBJECT_TYPE ObjectType
,
691 SECURITY_INFORMATION SecurityInfo
,
696 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
698 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
699 HMODULE hm_advapi32
= NULL
;
700 if (is_windows_9x () == TRUE
)
704 if (g_b_init_get_security_info
== 0)
706 g_b_init_get_security_info
= 1;
707 hm_advapi32
= LoadLibrary ("Advapi32.dll");
708 s_pfn_Get_Security_Info
=
709 (GetSecurityInfo_Proc
) GetProcAddress (
710 hm_advapi32
, "GetSecurityInfo");
712 if (s_pfn_Get_Security_Info
== NULL
)
716 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
717 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
718 ppSecurityDescriptor
));
722 get_file_security (const char *lpFileName
,
723 SECURITY_INFORMATION RequestedInformation
,
724 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
726 LPDWORD lpnLengthNeeded
)
728 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
729 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
730 HMODULE hm_advapi32
= NULL
;
731 if (is_windows_9x () == TRUE
)
736 if (w32_unicode_filenames
)
738 wchar_t filename_w
[MAX_PATH
];
740 if (g_b_init_get_file_security_w
== 0)
742 g_b_init_get_file_security_w
= 1;
743 hm_advapi32
= LoadLibrary ("Advapi32.dll");
744 s_pfn_Get_File_SecurityW
=
745 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
748 if (s_pfn_Get_File_SecurityW
== NULL
)
753 filename_to_utf16 (lpFileName
, filename_w
);
754 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
755 pSecurityDescriptor
, nLength
,
760 char filename_a
[MAX_PATH
];
762 if (g_b_init_get_file_security_a
== 0)
764 g_b_init_get_file_security_a
= 1;
765 hm_advapi32
= LoadLibrary ("Advapi32.dll");
766 s_pfn_Get_File_SecurityA
=
767 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
770 if (s_pfn_Get_File_SecurityA
== NULL
)
775 filename_to_ansi (lpFileName
, filename_a
);
776 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
777 pSecurityDescriptor
, nLength
,
783 set_file_security (const char *lpFileName
,
784 SECURITY_INFORMATION SecurityInformation
,
785 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
787 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
788 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
789 HMODULE hm_advapi32
= NULL
;
790 if (is_windows_9x () == TRUE
)
795 if (w32_unicode_filenames
)
797 wchar_t filename_w
[MAX_PATH
];
799 if (g_b_init_set_file_security_w
== 0)
801 g_b_init_set_file_security_w
= 1;
802 hm_advapi32
= LoadLibrary ("Advapi32.dll");
803 s_pfn_Set_File_SecurityW
=
804 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
807 if (s_pfn_Set_File_SecurityW
== NULL
)
812 filename_to_utf16 (lpFileName
, filename_w
);
813 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
814 pSecurityDescriptor
));
818 char filename_a
[MAX_PATH
];
820 if (g_b_init_set_file_security_a
== 0)
822 g_b_init_set_file_security_a
= 1;
823 hm_advapi32
= LoadLibrary ("Advapi32.dll");
824 s_pfn_Set_File_SecurityA
=
825 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
828 if (s_pfn_Set_File_SecurityA
== NULL
)
833 filename_to_ansi (lpFileName
, filename_a
);
834 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
835 pSecurityDescriptor
));
840 set_named_security_info (LPCTSTR lpObjectName
,
841 SE_OBJECT_TYPE ObjectType
,
842 SECURITY_INFORMATION SecurityInformation
,
848 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW
= NULL
;
849 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA
= NULL
;
850 HMODULE hm_advapi32
= NULL
;
851 if (is_windows_9x () == TRUE
)
856 if (w32_unicode_filenames
)
858 wchar_t filename_w
[MAX_PATH
];
860 if (g_b_init_set_named_security_info_w
== 0)
862 g_b_init_set_named_security_info_w
= 1;
863 hm_advapi32
= LoadLibrary ("Advapi32.dll");
864 s_pfn_Set_Named_Security_InfoW
=
865 (SetNamedSecurityInfoW_Proc
) GetProcAddress (hm_advapi32
,
866 "SetNamedSecurityInfoW");
868 if (s_pfn_Set_Named_Security_InfoW
== NULL
)
873 filename_to_utf16 (lpObjectName
, filename_w
);
874 return (s_pfn_Set_Named_Security_InfoW (filename_w
, ObjectType
,
875 SecurityInformation
, psidOwner
,
876 psidGroup
, pDacl
, pSacl
));
880 char filename_a
[MAX_PATH
];
882 if (g_b_init_set_named_security_info_a
== 0)
884 g_b_init_set_named_security_info_a
= 1;
885 hm_advapi32
= LoadLibrary ("Advapi32.dll");
886 s_pfn_Set_Named_Security_InfoA
=
887 (SetNamedSecurityInfoA_Proc
) GetProcAddress (hm_advapi32
,
888 "SetNamedSecurityInfoA");
890 if (s_pfn_Set_Named_Security_InfoA
== NULL
)
895 filename_to_ansi (lpObjectName
, filename_a
);
896 return (s_pfn_Set_Named_Security_InfoA (filename_a
, ObjectType
,
897 SecurityInformation
, psidOwner
,
898 psidGroup
, pDacl
, pSacl
));
903 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
905 LPBOOL lpbOwnerDefaulted
)
907 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
908 HMODULE hm_advapi32
= NULL
;
909 if (is_windows_9x () == TRUE
)
914 if (g_b_init_get_security_descriptor_owner
== 0)
916 g_b_init_get_security_descriptor_owner
= 1;
917 hm_advapi32
= LoadLibrary ("Advapi32.dll");
918 s_pfn_Get_Security_Descriptor_Owner
=
919 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
920 hm_advapi32
, "GetSecurityDescriptorOwner");
922 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
927 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
932 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
934 LPBOOL lpbGroupDefaulted
)
936 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
937 HMODULE hm_advapi32
= NULL
;
938 if (is_windows_9x () == TRUE
)
943 if (g_b_init_get_security_descriptor_group
== 0)
945 g_b_init_get_security_descriptor_group
= 1;
946 hm_advapi32
= LoadLibrary ("Advapi32.dll");
947 s_pfn_Get_Security_Descriptor_Group
=
948 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
949 hm_advapi32
, "GetSecurityDescriptorGroup");
951 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
956 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
961 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
962 LPBOOL lpbDaclPresent
,
964 LPBOOL lpbDaclDefaulted
)
966 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
967 HMODULE hm_advapi32
= NULL
;
968 if (is_windows_9x () == TRUE
)
973 if (g_b_init_get_security_descriptor_dacl
== 0)
975 g_b_init_get_security_descriptor_dacl
= 1;
976 hm_advapi32
= LoadLibrary ("Advapi32.dll");
977 s_pfn_Get_Security_Descriptor_Dacl
=
978 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
979 hm_advapi32
, "GetSecurityDescriptorDacl");
981 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
986 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
987 lpbDaclPresent
, pDacl
,
992 is_valid_sid (PSID sid
)
994 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
995 HMODULE hm_advapi32
= NULL
;
996 if (is_windows_9x () == TRUE
)
1000 if (g_b_init_is_valid_sid
== 0)
1002 g_b_init_is_valid_sid
= 1;
1003 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1004 s_pfn_Is_Valid_Sid
=
1005 (IsValidSid_Proc
) GetProcAddress (
1006 hm_advapi32
, "IsValidSid");
1008 if (s_pfn_Is_Valid_Sid
== NULL
)
1012 return (s_pfn_Is_Valid_Sid (sid
));
1016 equal_sid (PSID sid1
, PSID sid2
)
1018 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
1019 HMODULE hm_advapi32
= NULL
;
1020 if (is_windows_9x () == TRUE
)
1024 if (g_b_init_equal_sid
== 0)
1026 g_b_init_equal_sid
= 1;
1027 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1029 (EqualSid_Proc
) GetProcAddress (
1030 hm_advapi32
, "EqualSid");
1032 if (s_pfn_Equal_Sid
== NULL
)
1036 return (s_pfn_Equal_Sid (sid1
, sid2
));
1040 get_length_sid (PSID sid
)
1042 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
1043 HMODULE hm_advapi32
= NULL
;
1044 if (is_windows_9x () == TRUE
)
1048 if (g_b_init_get_length_sid
== 0)
1050 g_b_init_get_length_sid
= 1;
1051 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1052 s_pfn_Get_Length_Sid
=
1053 (GetLengthSid_Proc
) GetProcAddress (
1054 hm_advapi32
, "GetLengthSid");
1056 if (s_pfn_Get_Length_Sid
== NULL
)
1060 return (s_pfn_Get_Length_Sid (sid
));
1064 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
1066 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
1067 HMODULE hm_advapi32
= NULL
;
1068 if (is_windows_9x () == TRUE
)
1072 if (g_b_init_copy_sid
== 0)
1074 g_b_init_copy_sid
= 1;
1075 hm_advapi32
= LoadLibrary ("Advapi32.dll");
1077 (CopySid_Proc
) GetProcAddress (
1078 hm_advapi32
, "CopySid");
1080 if (s_pfn_Copy_Sid
== NULL
)
1084 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1088 END: Wrapper functions around OpenProcessToken
1089 and other functions in advapi32.dll that are only
1090 supported in Windows NT / 2k / XP
1094 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1096 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1097 if (is_windows_9x () != TRUE
)
1099 if (g_b_init_get_native_system_info
== 0)
1101 g_b_init_get_native_system_info
= 1;
1102 s_pfn_Get_Native_System_Info
=
1103 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1104 "GetNativeSystemInfo");
1106 if (s_pfn_Get_Native_System_Info
!= NULL
)
1107 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1110 lpSystemInfo
->dwNumberOfProcessors
= -1;
1114 get_system_times (LPFILETIME lpIdleTime
,
1115 LPFILETIME lpKernelTime
,
1116 LPFILETIME lpUserTime
)
1118 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1119 if (is_windows_9x () == TRUE
)
1123 if (g_b_init_get_system_times
== 0)
1125 g_b_init_get_system_times
= 1;
1126 s_pfn_Get_System_times
=
1127 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1130 if (s_pfn_Get_System_times
== NULL
)
1132 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1135 static BOOLEAN WINAPI
1136 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1137 LPCSTR lpTargetFileName
,
1140 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1141 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1144 if (is_windows_9x () == TRUE
)
1149 if (w32_unicode_filenames
)
1151 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1153 if (g_b_init_create_symbolic_link_w
== 0)
1155 g_b_init_create_symbolic_link_w
= 1;
1156 s_pfn_Create_Symbolic_LinkW
=
1157 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1158 "CreateSymbolicLinkW");
1160 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1166 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1167 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1168 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1169 /* If we were denied creation of the symlink, try again after
1170 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1173 TOKEN_PRIVILEGES priv_current
;
1175 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1178 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1179 restore_privilege (&priv_current
);
1186 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1188 if (g_b_init_create_symbolic_link_a
== 0)
1190 g_b_init_create_symbolic_link_a
= 1;
1191 s_pfn_Create_Symbolic_LinkA
=
1192 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1193 "CreateSymbolicLinkA");
1195 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1201 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1202 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1203 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1204 /* If we were denied creation of the symlink, try again after
1205 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1208 TOKEN_PRIVILEGES priv_current
;
1210 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1213 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1214 restore_privilege (&priv_current
);
1223 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1225 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1227 if (is_windows_9x () == TRUE
)
1233 if (g_b_init_is_valid_security_descriptor
== 0)
1235 g_b_init_is_valid_security_descriptor
= 1;
1236 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1237 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1238 "IsValidSecurityDescriptor");
1240 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1246 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1250 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1251 DWORD RequestedStringSDRevision
,
1252 SECURITY_INFORMATION SecurityInformation
,
1253 LPTSTR
*StringSecurityDescriptor
,
1254 PULONG StringSecurityDescriptorLen
)
1256 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1259 if (is_windows_9x () == TRUE
)
1265 if (g_b_init_convert_sd_to_sddl
== 0)
1267 g_b_init_convert_sd_to_sddl
= 1;
1269 s_pfn_Convert_SD_To_SDDL
=
1270 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1271 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1273 s_pfn_Convert_SD_To_SDDL
=
1274 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1275 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1278 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1284 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1285 RequestedStringSDRevision
,
1286 SecurityInformation
,
1287 StringSecurityDescriptor
,
1288 StringSecurityDescriptorLen
);
1294 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1295 DWORD StringSDRevision
,
1296 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1297 PULONG SecurityDescriptorSize
)
1299 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1302 if (is_windows_9x () == TRUE
)
1308 if (g_b_init_convert_sddl_to_sd
== 0)
1310 g_b_init_convert_sddl_to_sd
= 1;
1312 s_pfn_Convert_SDDL_To_SD
=
1313 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1314 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1316 s_pfn_Convert_SDDL_To_SD
=
1317 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1318 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1321 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1327 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1330 SecurityDescriptorSize
);
1336 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1338 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1339 HMODULE hm_iphlpapi
= NULL
;
1341 if (is_windows_9x () == TRUE
)
1342 return ERROR_NOT_SUPPORTED
;
1344 if (g_b_init_get_adapters_info
== 0)
1346 g_b_init_get_adapters_info
= 1;
1347 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1349 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1350 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1352 if (s_pfn_Get_Adapters_Info
== NULL
)
1353 return ERROR_NOT_SUPPORTED
;
1354 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1359 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1360 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1362 This is called from alloc.c:valid_pointer_p. */
1364 w32_valid_pointer_p (void *p
, int size
)
1367 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1371 unsigned char *buf
= alloca (size
);
1372 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1383 /* Here's an overview of how the Windows build supports file names
1384 that cannot be encoded by the current system codepage.
1386 From the POV of Lisp and layers of C code above the functions here,
1387 Emacs on Windows pretends that its file names are encoded in UTF-8;
1388 see encode_file and decode_file on coding.c. Any file name that is
1389 passed as a unibyte string to C functions defined here is assumed
1390 to be in UTF-8 encoding. Any file name returned by functions
1391 defined here must be in UTF-8 encoding, with only a few exceptions
1392 reserved for a couple of special cases. (Be sure to use
1393 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1394 as they can be much longer than MAX_PATH!)
1396 The UTF-8 encoded file names cannot be passed to system APIs, as
1397 Windows does not support that. Therefore, they are converted
1398 either to UTF-16 or to the ANSI codepage, depending on the value of
1399 w32-unicode-filenames, before calling any system APIs or CRT library
1400 functions. The default value of that variable is determined by the
1401 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1402 user can change that default (although I don't see why would she
1405 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1406 filename_from_utf16, and filename_from_ansi, are the workhorses of
1407 these conversions. They rely on Windows native APIs
1408 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1409 functions from coding.c here, because they allocate memory, which
1410 is a bad idea on the level of libc, which is what the functions
1411 here emulate. (If you worry about performance due to constant
1412 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1413 it was measured to take only a few microseconds on a not-so-fast
1414 machine, and second, that's exactly what the ANSI APIs we used
1415 before did anyway, because they are just thin wrappers around the
1418 The variables file-name-coding-system and default-file-name-coding-system
1419 still exist, but are actually used only when a file name needs to
1420 be converted to the ANSI codepage. This happens all the time when
1421 w32-unicode-filenames is nil, but can also happen from time to time
1422 when it is t. Otherwise, these variables have no effect on file-name
1423 encoding when w32-unicode-filenames is t; this is similar to
1424 selection-coding-system.
1426 This arrangement works very well, but it has a few gotchas and
1429 . Lisp code that encodes or decodes file names manually should
1430 normally use 'utf-8' as the coding-system on Windows,
1431 disregarding file-name-coding-system. This is a somewhat
1432 unpleasant consequence, but it cannot be avoided. Fortunately,
1433 very few Lisp packages need to do that.
1435 More generally, passing to library functions (e.g., fopen or
1436 opendir) file names already encoded in the ANSI codepage is
1437 explicitly *verboten*, as all those functions, as shadowed and
1438 emulated here, assume they will receive UTF-8 encoded file names.
1440 For the same reasons, no CRT function or Win32 API can be called
1441 directly in Emacs sources, without either converting the file
1442 names from UTF-8 to UTF-16 or ANSI codepage, or going through
1443 some shadowing function defined here.
1445 . Environment variables stored in Vprocess_environment are encoded
1446 in the ANSI codepage, so if getenv/egetenv is used for a variable
1447 whose value is a file name or a list of directories, it needs to
1448 be converted to UTF-8, before it is used as argument to functions
1449 or decoded into a Lisp string.
1451 . File names passed to external libraries, like the image libraries
1452 and GnuTLS, need special handling. These libraries generally
1453 don't support UTF-16 or UTF-8 file names, so they must get file
1454 names encoded in the ANSI codepage. To facilitate using these
1455 libraries with file names that are not encodable in the ANSI
1456 codepage, use the function ansi_encode_filename, which will try
1457 to use the short 8+3 alias of a file name if that file name is
1458 not encodable in the ANSI codepage. See image.c and gnutls.c for
1459 examples of how this should be done.
1461 . Running subprocesses in non-ASCII directories and with non-ASCII
1462 file arguments is limited to the current codepage (even though
1463 Emacs is perfectly capable of finding an executable program file
1464 in a directory whose name cannot be encoded in the current
1465 codepage). This is because the command-line arguments are
1466 encoded _before_ they get to the w32-specific level, and the
1467 encoding is not known in advance (it doesn't have to be the
1468 current ANSI codepage), so w32proc.c functions cannot re-encode
1469 them in UTF-16. This should be fixed, but will also require
1470 changes in cmdproxy. The current limitation is not terribly bad
1471 anyway, since very few, if any, Windows console programs that are
1472 likely to be invoked by Emacs support UTF-16 encoded command
1475 . For similar reasons, server.el and emacsclient are also limited
1476 to the current ANSI codepage for now.
1478 . Emacs itself can only handle command-line arguments encoded in
1479 the current codepage.
1481 . Turning on w32-unicode-filename on Windows 9X (if it at all
1482 works) requires UNICOWS.DLL, which is thus a requirement even in
1483 non-GUI sessions, something the we previously avoided. */
1487 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1488 codepage defined by file-name-coding-system. */
1490 /* Current codepage for encoding file names. */
1491 static int file_name_codepage
;
1493 /* Produce a Windows ANSI codepage suitable for encoding file names.
1494 Return the information about that codepage in CP_INFO. */
1496 codepage_for_filenames (CPINFO
*cp_info
)
1498 /* A simple cache to avoid calling GetCPInfo every time we need to
1499 encode/decode a file name. The file-name encoding is not
1500 supposed to be changed too frequently, if ever. */
1501 static Lisp_Object last_file_name_encoding
;
1503 Lisp_Object current_encoding
;
1505 current_encoding
= Vfile_name_coding_system
;
1506 if (NILP (current_encoding
))
1507 current_encoding
= Vdefault_file_name_coding_system
;
1509 if (!EQ (last_file_name_encoding
, current_encoding
))
1511 /* Default to the current ANSI codepage. */
1512 file_name_codepage
= w32_ansi_code_page
;
1514 if (NILP (current_encoding
))
1516 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1517 char *cp
= NULL
, *end
;
1520 if (strncmp (cpname
, "cp", 2) == 0)
1522 else if (strncmp (cpname
, "windows-", 8) == 0)
1528 cpnum
= strtol (cp
, &end
, 10);
1529 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1530 file_name_codepage
= cpnum
;
1534 if (!file_name_codepage
)
1535 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1537 if (!GetCPInfo (file_name_codepage
, &cp
))
1539 file_name_codepage
= CP_ACP
;
1540 if (!GetCPInfo (file_name_codepage
, &cp
))
1547 return file_name_codepage
;
1551 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1553 int result
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1558 DWORD err
= GetLastError ();
1562 case ERROR_INVALID_FLAGS
:
1563 case ERROR_INVALID_PARAMETER
:
1566 case ERROR_INSUFFICIENT_BUFFER
:
1567 case ERROR_NO_UNICODE_TRANSLATION
:
1578 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1580 int result
= pWideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1581 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1585 DWORD err
= GetLastError ();
1589 case ERROR_INVALID_FLAGS
:
1590 case ERROR_INVALID_PARAMETER
:
1593 case ERROR_INSUFFICIENT_BUFFER
:
1594 case ERROR_NO_UNICODE_TRANSLATION
:
1605 filename_to_ansi (const char *fn_in
, char *fn_out
)
1607 wchar_t fn_utf16
[MAX_PATH
];
1609 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1612 int codepage
= codepage_for_filenames (NULL
);
1614 result
= pWideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1615 fn_out
, MAX_PATH
, NULL
, NULL
);
1618 DWORD err
= GetLastError ();
1622 case ERROR_INVALID_FLAGS
:
1623 case ERROR_INVALID_PARAMETER
:
1626 case ERROR_INSUFFICIENT_BUFFER
:
1627 case ERROR_NO_UNICODE_TRANSLATION
:
1640 filename_from_ansi (const char *fn_in
, char *fn_out
)
1642 wchar_t fn_utf16
[MAX_PATH
];
1643 int codepage
= codepage_for_filenames (NULL
);
1644 int result
= pMultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1645 fn_utf16
, MAX_PATH
);
1649 DWORD err
= GetLastError ();
1653 case ERROR_INVALID_FLAGS
:
1654 case ERROR_INVALID_PARAMETER
:
1657 case ERROR_INSUFFICIENT_BUFFER
:
1658 case ERROR_NO_UNICODE_TRANSLATION
:
1665 return filename_from_utf16 (fn_utf16
, fn_out
);
1670 /* The directory where we started, in UTF-8. */
1671 static char startup_dir
[MAX_UTF8_PATH
];
1673 /* Get the current working directory. */
1675 getcwd (char *dir
, int dirsize
)
1682 if (dirsize
<= strlen (startup_dir
))
1688 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1692 /* Emacs doesn't actually change directory itself, it stays in the
1693 same directory where it was started. */
1694 strcpy (dir
, startup_dir
);
1699 /* Emulate getloadavg. */
1701 struct load_sample
{
1708 /* Number of processors on this machine. */
1709 static unsigned num_of_processors
;
1711 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1712 static struct load_sample samples
[16*60];
1713 static int first_idx
= -1, last_idx
= -1;
1714 static int max_idx
= ARRAYELTS (samples
);
1719 int next_idx
= from
+ 1;
1721 if (next_idx
>= max_idx
)
1730 int prev_idx
= from
- 1;
1733 prev_idx
= max_idx
- 1;
1739 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1741 SYSTEM_INFO sysinfo
;
1742 FILETIME ft_idle
, ft_user
, ft_kernel
;
1744 /* Initialize the number of processors on this machine. */
1745 if (num_of_processors
<= 0)
1747 get_native_system_info (&sysinfo
);
1748 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1749 if (num_of_processors
<= 0)
1751 GetSystemInfo (&sysinfo
);
1752 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1754 if (num_of_processors
<= 0)
1755 num_of_processors
= 1;
1758 /* TODO: Take into account threads that are ready to run, by
1759 sampling the "\System\Processor Queue Length" performance
1760 counter. The code below accounts only for threads that are
1761 actually running. */
1763 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1765 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1767 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1768 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1769 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1770 *idle
= uidle
.QuadPart
;
1771 *kernel
= ukernel
.QuadPart
;
1772 *user
= uuser
.QuadPart
;
1782 /* Produce the load average for a given time interval, using the
1783 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1784 1-minute, 5-minute, or 15-minute average, respectively. */
1788 double retval
= -1.0;
1791 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1792 time_t now
= samples
[last_idx
].sample_time
;
1794 if (first_idx
!= last_idx
)
1796 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1798 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1799 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1802 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1803 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1804 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1806 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1809 if (idx
== first_idx
)
1818 getloadavg (double loadavg
[], int nelem
)
1821 ULONGLONG idle
, kernel
, user
;
1822 time_t now
= time (NULL
);
1824 /* If system time jumped back for some reason, delete all samples
1825 whose time is later than the current wall-clock time. This
1826 prevents load average figures from becoming frozen for prolonged
1827 periods of time, when system time is reset backwards. */
1830 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1832 if (last_idx
== first_idx
)
1834 first_idx
= last_idx
= -1;
1837 last_idx
= buf_prev (last_idx
);
1841 /* Store another sample. We ignore samples that are less than 1 sec
1844 || (difftime (now
, samples
[last_idx
].sample_time
)
1845 >= 1.0 - 2*DBL_EPSILON
*now
))
1847 sample_system_load (&idle
, &kernel
, &user
);
1848 last_idx
= buf_next (last_idx
);
1849 samples
[last_idx
].sample_time
= now
;
1850 samples
[last_idx
].idle
= idle
;
1851 samples
[last_idx
].kernel
= kernel
;
1852 samples
[last_idx
].user
= user
;
1853 /* If the buffer has more that 15 min worth of samples, discard
1855 if (first_idx
== -1)
1856 first_idx
= last_idx
;
1857 while (first_idx
!= last_idx
1858 && (difftime (now
, samples
[first_idx
].sample_time
)
1859 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1860 first_idx
= buf_next (first_idx
);
1863 for (elem
= 0; elem
< nelem
; elem
++)
1865 double avg
= getavg (elem
);
1869 loadavg
[elem
] = avg
;
1875 /* Emulate getpwuid, getpwnam and others. */
1877 #define PASSWD_FIELD_SIZE 256
1879 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1880 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1881 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1882 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1883 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1885 static struct passwd dflt_passwd
=
1897 static char dflt_group_name
[GNLEN
+1];
1899 static struct group dflt_group
=
1901 /* When group information is not available, we return this as the
1902 group for all files. */
1910 return dflt_passwd
.pw_uid
;
1916 /* I could imagine arguing for checking to see whether the user is
1917 in the Administrators group and returning a UID of 0 for that
1918 case, but I don't know how wise that would be in the long run. */
1925 return dflt_passwd
.pw_gid
;
1935 getpwuid (unsigned uid
)
1937 if (uid
== dflt_passwd
.pw_uid
)
1938 return &dflt_passwd
;
1943 getgrgid (gid_t gid
)
1949 getpwnam (char *name
)
1953 pw
= getpwuid (getuid ());
1957 if (xstrcasecmp (name
, pw
->pw_name
))
1964 init_user_info (void)
1966 /* Find the user's real name by opening the process token and
1967 looking up the name associated with the user-sid in that token.
1969 Use the relative portion of the identifier authority value from
1970 the user-sid as the user id value (same for group id using the
1971 primary group sid from the process token). */
1973 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1974 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1975 DWORD glength
= sizeof (gname
);
1976 HANDLE token
= NULL
;
1977 SID_NAME_USE user_type
;
1978 unsigned char *buf
= NULL
;
1980 TOKEN_USER user_token
;
1981 TOKEN_PRIMARY_GROUP group_token
;
1984 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1987 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1988 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1990 buf
= xmalloc (blen
);
1991 result
= get_token_information (token
, TokenUser
,
1992 (LPVOID
)buf
, blen
, &needed
);
1995 memcpy (&user_token
, buf
, sizeof (user_token
));
1996 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1998 domain
, &dlength
, &user_type
);
2006 strcpy (dflt_passwd
.pw_name
, uname
);
2007 /* Determine a reasonable uid value. */
2008 if (xstrcasecmp ("administrator", uname
) == 0)
2010 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
2011 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
2015 /* Use the last sub-authority value of the RID, the relative
2016 portion of the SID, as user/group ID. */
2017 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
2019 /* Get group id and name. */
2020 result
= get_token_information (token
, TokenPrimaryGroup
,
2021 (LPVOID
)buf
, blen
, &needed
);
2022 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
2024 buf
= xrealloc (buf
, blen
= needed
);
2025 result
= get_token_information (token
, TokenPrimaryGroup
,
2026 (LPVOID
)buf
, blen
, &needed
);
2030 memcpy (&group_token
, buf
, sizeof (group_token
));
2031 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
2032 dlength
= sizeof (domain
);
2033 /* If we can get at the real Primary Group name, use that.
2034 Otherwise, the default group name was already set to
2035 "None" in globals_of_w32. */
2036 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
2037 gname
, &glength
, NULL
, &dlength
,
2039 strcpy (dflt_group_name
, gname
);
2042 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2045 /* If security calls are not supported (presumably because we
2046 are running under Windows 9X), fallback to this: */
2047 else if (GetUserName (uname
, &ulength
))
2049 strcpy (dflt_passwd
.pw_name
, uname
);
2050 if (xstrcasecmp ("administrator", uname
) == 0)
2051 dflt_passwd
.pw_uid
= 0;
2053 dflt_passwd
.pw_uid
= 123;
2054 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
2058 strcpy (dflt_passwd
.pw_name
, "unknown");
2059 dflt_passwd
.pw_uid
= 123;
2060 dflt_passwd
.pw_gid
= 123;
2062 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
2064 /* Set dir and shell from environment variables. */
2065 if (w32_unicode_filenames
)
2067 wchar_t *home
= _wgetenv (L
"HOME");
2068 wchar_t *shell
= _wgetenv (L
"SHELL");
2070 /* Ensure HOME and SHELL are defined. */
2075 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
2076 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
2080 char *home
= getenv ("HOME");
2081 char *shell
= getenv ("SHELL");
2087 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2088 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2093 CloseHandle (token
);
2099 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2100 return ((rand () << 15) | rand ());
2109 /* Return the maximum length in bytes of a multibyte character
2110 sequence encoded in the current ANSI codepage. This is required to
2111 correctly walk the encoded file names one character at a time. */
2113 max_filename_mbslen (void)
2117 codepage_for_filenames (&cp_info
);
2118 return cp_info
.MaxCharSize
;
2121 /* Normalize filename by converting in-place all of its path
2122 separators to the separator specified by PATH_SEP. */
2125 normalize_filename (register char *fp
, char path_sep
)
2129 /* Always lower-case drive letters a-z, even if the filesystem
2130 preserves case in filenames.
2131 This is so filenames can be compared by string comparison
2132 functions that are case-sensitive. Even case-preserving filesystems
2133 do not distinguish case in drive letters. */
2136 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2144 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2150 /* Destructively turn backslashes into slashes. */
2152 dostounix_filename (register char *p
)
2154 normalize_filename (p
, '/');
2157 /* Destructively turn slashes into backslashes. */
2159 unixtodos_filename (register char *p
)
2161 normalize_filename (p
, '\\');
2164 /* Remove all CR's that are followed by a LF.
2165 (From msdos.c...probably should figure out a way to share it,
2166 although this code isn't going to ever change.) */
2168 crlf_to_lf (register int n
, register unsigned char *buf
)
2170 unsigned char *np
= buf
;
2171 unsigned char *startp
= buf
;
2172 unsigned char *endp
= buf
+ n
;
2176 while (buf
< endp
- 1)
2180 if (*(++buf
) != 0x0a)
2191 /* Parse the root part of file name, if present. Return length and
2192 optionally store pointer to char after root. */
2194 parse_root (const char * name
, const char ** pPath
)
2196 const char * start
= name
;
2201 /* find the root name of the volume if given */
2202 if (isalpha (name
[0]) && name
[1] == ':')
2204 /* skip past drive specifier */
2206 if (IS_DIRECTORY_SEP (name
[0]))
2209 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2216 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2221 if (IS_DIRECTORY_SEP (name
[0]))
2228 return name
- start
;
2231 /* Get long base name for name; name is assumed to be absolute. */
2233 get_long_basename (char * name
, char * buf
, int size
)
2235 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2236 char fname_utf8
[MAX_UTF8_PATH
];
2240 /* Must be valid filename, no wild cards or other invalid characters. */
2241 if (strpbrk (name
, "*?|<>\""))
2244 if (w32_unicode_filenames
)
2246 wchar_t fname_utf16
[MAX_PATH
];
2247 WIN32_FIND_DATAW find_data_wide
;
2249 filename_to_utf16 (name
, fname_utf16
);
2250 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2251 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2252 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2256 char fname_ansi
[MAX_PATH
];
2257 WIN32_FIND_DATAA find_data_ansi
;
2259 filename_to_ansi (name
, fname_ansi
);
2260 /* If the ANSI name includes ? characters, it is not encodable
2261 in the ANSI codepage. In that case, we deliver the question
2262 marks to the caller; calling FindFirstFileA in this case
2263 could return some unrelated file name in the same
2265 if (_mbspbrk (fname_ansi
, "?"))
2267 /* Find the basename of fname_ansi. */
2268 char *p
= strrchr (fname_ansi
, '\\');
2274 cstatus
= filename_from_ansi (p
, fname_utf8
);
2278 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2279 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2280 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2284 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2285 memcpy (buf
, fname_utf8
, len
+ 1);
2289 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2290 FindClose (dir_handle
);
2295 /* Get long name for file, if possible (assumed to be absolute). */
2297 w32_get_long_filename (char * name
, char * buf
, int size
)
2302 char full
[ MAX_UTF8_PATH
];
2305 len
= strlen (name
);
2306 if (len
>= MAX_UTF8_PATH
)
2309 /* Use local copy for destructive modification. */
2310 memcpy (full
, name
, len
+1);
2311 unixtodos_filename (full
);
2313 /* Copy root part verbatim. */
2314 len
= parse_root (full
, (const char **)&p
);
2315 memcpy (o
, full
, len
);
2320 while (p
!= NULL
&& *p
)
2323 p
= strchr (q
, '\\');
2325 len
= get_long_basename (full
, o
, size
);
2348 w32_get_short_filename (char * name
, char * buf
, int size
)
2350 if (w32_unicode_filenames
)
2352 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2353 unsigned int retval
;
2355 filename_to_utf16 (name
, name_utf16
);
2356 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2357 if (retval
&& retval
< size
)
2358 filename_from_utf16 (short_name
, buf
);
2363 char name_ansi
[MAX_PATH
];
2365 filename_to_ansi (name
, name_ansi
);
2366 return GetShortPathNameA (name_ansi
, buf
, size
);
2370 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2371 MS-Windows ANSI codepage. If FILENAME includes characters not
2372 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2373 if it exists. This is needed because the w32 build wants to
2374 support file names outside of the system locale, but image
2375 libraries typically don't support wide (a.k.a. "Unicode") APIs
2376 required for that. */
2379 ansi_encode_filename (Lisp_Object filename
)
2381 Lisp_Object encoded_filename
;
2382 char fname
[MAX_PATH
];
2384 filename_to_ansi (SSDATA (filename
), fname
);
2385 if (_mbspbrk (fname
, "?"))
2387 char shortname
[MAX_PATH
];
2389 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2391 dostounix_filename (shortname
);
2392 encoded_filename
= build_string (shortname
);
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
) - 1;
3407 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3408 strcat (filename
, "\\");
3409 strcat (filename
, "*");
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
)
3438 else if (w32_unicode_filenames
)
3440 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3445 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3449 /* Emacs never uses this value, so don't bother making it match
3450 value returned by stat(). */
3451 dir_static
.d_ino
= 1;
3453 if (w32_unicode_filenames
)
3455 if (downcase
|| dir_is_fat
)
3457 wchar_t tem
[MAX_PATH
];
3459 wcscpy (tem
, dir_find_data_w
.cFileName
);
3461 filename_from_utf16 (tem
, dir_static
.d_name
);
3464 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3465 last_dir_find_data
= DIR_FIND_DATA_W
;
3471 /* If the file name in cFileName[] includes `?' characters, it
3472 means the original file name used characters that cannot be
3473 represented by the current ANSI codepage. To avoid total
3474 lossage, retrieve the short 8+3 alias of the long file
3476 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3478 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3479 /* 8+3 aliases are returned in all caps, which could break
3480 various alists that look at filenames' extensions. */
3483 else if (downcase
|| dir_is_fat
)
3484 strcpy (tem
, dir_find_data_a
.cFileName
);
3486 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3487 if (downcase
|| dir_is_fat
)
3490 filename_from_ansi (tem
, dir_static
.d_name
);
3492 last_dir_find_data
= DIR_FIND_DATA_A
;
3495 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3496 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3497 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3503 open_unc_volume (const char *path
)
3505 const char *fn
= map_w32_filename (path
, NULL
);
3509 if (w32_unicode_filenames
)
3512 wchar_t fnw
[MAX_PATH
];
3514 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3515 nrw
.dwType
= RESOURCETYPE_DISK
;
3516 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3517 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3518 nrw
.lpLocalName
= NULL
;
3519 filename_to_utf16 (fn
, fnw
);
3520 nrw
.lpRemoteName
= fnw
;
3521 nrw
.lpComment
= NULL
;
3522 nrw
.lpProvider
= NULL
;
3524 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3525 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3532 nra
.dwScope
= RESOURCE_GLOBALNET
;
3533 nra
.dwType
= RESOURCETYPE_DISK
;
3534 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3535 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3536 nra
.lpLocalName
= NULL
;
3537 filename_to_ansi (fn
, fna
);
3538 nra
.lpRemoteName
= fna
;
3539 nra
.lpComment
= NULL
;
3540 nra
.lpProvider
= NULL
;
3542 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3543 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3545 if (result
== NO_ERROR
)
3548 return INVALID_HANDLE_VALUE
;
3552 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3557 DWORD bufsize
= 512;
3561 if (w32_unicode_filenames
)
3566 buffer
= alloca (bufsize
);
3567 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3568 if (result
!= NO_ERROR
)
3570 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3571 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3573 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3575 wcsncpy (fname_w
, ptrw
, size
);
3580 int dbcs_p
= max_filename_mbslen () > 1;
3583 buffer
= alloca (bufsize
);
3584 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3585 if (result
!= NO_ERROR
)
3587 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3590 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3593 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3594 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3597 strncpy (fname_a
, ptra
, size
);
3605 close_unc_volume (HANDLE henum
)
3607 if (henum
!= INVALID_HANDLE_VALUE
)
3608 WNetCloseEnum (henum
);
3612 unc_volume_file_attributes (const char *path
)
3617 henum
= open_unc_volume (path
);
3618 if (henum
== INVALID_HANDLE_VALUE
)
3621 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3623 close_unc_volume (henum
);
3628 /* Ensure a network connection is authenticated. */
3630 logon_network_drive (const char *path
)
3632 char share
[MAX_UTF8_PATH
];
3639 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3640 drvtype
= DRIVE_REMOTE
;
3641 else if (path
[0] == '\0' || path
[1] != ':')
3642 drvtype
= GetDriveType (NULL
);
3649 drvtype
= GetDriveType (drive
);
3652 /* Only logon to networked drives. */
3653 if (drvtype
!= DRIVE_REMOTE
)
3657 strncpy (share
, path
, MAX_UTF8_PATH
);
3658 /* Truncate to just server and share name. */
3659 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3661 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3668 if (w32_unicode_filenames
)
3670 NETRESOURCEW resourcew
;
3671 wchar_t share_w
[MAX_PATH
];
3673 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3674 resourcew
.dwType
= RESOURCETYPE_DISK
;
3675 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3676 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3677 resourcew
.lpLocalName
= NULL
;
3678 filename_to_utf16 (share
, share_w
);
3679 resourcew
.lpRemoteName
= share_w
;
3680 resourcew
.lpProvider
= NULL
;
3682 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3686 NETRESOURCEA resourcea
;
3687 char share_a
[MAX_PATH
];
3689 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3690 resourcea
.dwType
= RESOURCETYPE_DISK
;
3691 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3692 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3693 resourcea
.lpLocalName
= NULL
;
3694 filename_to_ansi (share
, share_a
);
3695 resourcea
.lpRemoteName
= share_a
;
3696 resourcea
.lpProvider
= NULL
;
3698 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3704 case ERROR_ALREADY_ASSIGNED
:
3706 case ERROR_ACCESS_DENIED
:
3707 case ERROR_LOGON_FAILURE
:
3713 case ERROR_BAD_NET_NAME
:
3714 case ERROR_NO_NET_OR_BAD_PATH
:
3715 case ERROR_NO_NETWORK
:
3716 case ERROR_CANCELLED
:
3723 /* Emulate faccessat(2). */
3725 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3729 if (dirfd
!= AT_FDCWD
3730 && !(IS_DIRECTORY_SEP (path
[0])
3731 || IS_DEVICE_SEP (path
[1])))
3737 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3738 newer versions blow up when passed D_OK. */
3739 path
= map_w32_filename (path
, NULL
);
3740 /* If the last element of PATH is a symlink, we need to resolve it
3741 to get the attributes of its target file. Note: any symlinks in
3742 PATH elements other than the last one are transparently resolved
3743 by GetFileAttributes below. */
3744 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3745 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3746 path
= chase_symlinks (path
);
3748 if (w32_unicode_filenames
)
3750 wchar_t path_w
[MAX_PATH
];
3752 filename_to_utf16 (path
, path_w
);
3753 attributes
= GetFileAttributesW (path_w
);
3757 char path_a
[MAX_PATH
];
3759 filename_to_ansi (path
, path_a
);
3760 attributes
= GetFileAttributesA (path_a
);
3763 if (attributes
== -1)
3765 DWORD w32err
= GetLastError ();
3769 case ERROR_INVALID_NAME
:
3770 case ERROR_BAD_PATHNAME
:
3771 if (is_unc_volume (path
))
3773 attributes
= unc_volume_file_attributes (path
);
3774 if (attributes
== -1)
3782 case ERROR_FILE_NOT_FOUND
:
3783 case ERROR_BAD_NETPATH
:
3792 if ((mode
& X_OK
) != 0
3793 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3798 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3803 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3811 /* A version of 'access' to be used locally with file names in
3812 locale-specific encoding. Does not resolve symlinks and does not
3813 support file names on FAT12 and FAT16 volumes, but that's OK, since
3814 we only invoke this function for files inside the Emacs source or
3815 installation tree, on directories (so any symlinks should have the
3816 directory bit set), and on short file names such as "C:/.emacs". */
3818 sys_access (const char *fname
, int mode
)
3820 char fname_copy
[MAX_PATH
], *p
;
3823 strcpy (fname_copy
, fname
);
3824 /* Do the equivalent of unixtodos_filename. */
3825 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3829 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3831 DWORD w32err
= GetLastError ();
3835 case ERROR_INVALID_NAME
:
3836 case ERROR_BAD_PATHNAME
:
3837 case ERROR_FILE_NOT_FOUND
:
3838 case ERROR_BAD_NETPATH
:
3847 if ((mode
& X_OK
) != 0
3848 && !(is_exec (fname_copy
)
3849 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3854 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3859 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3867 /* Shadow some MSVC runtime functions to map requests for long filenames
3868 to reasonable short names if necessary. This was originally added to
3869 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3873 sys_chdir (const char * path
)
3875 path
= map_w32_filename (path
, NULL
);
3876 if (w32_unicode_filenames
)
3878 wchar_t newdir_w
[MAX_PATH
];
3880 if (filename_to_utf16 (path
, newdir_w
) == 0)
3881 return _wchdir (newdir_w
);
3886 char newdir_a
[MAX_PATH
];
3888 if (filename_to_ansi (path
, newdir_a
) == 0)
3889 return _chdir (newdir_a
);
3895 sys_chmod (const char * path
, int mode
)
3897 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3898 if (w32_unicode_filenames
)
3900 wchar_t path_w
[MAX_PATH
];
3902 filename_to_utf16 (path
, path_w
);
3903 return _wchmod (path_w
, mode
);
3907 char path_a
[MAX_PATH
];
3909 filename_to_ansi (path
, path_a
);
3910 return _chmod (path_a
, mode
);
3915 sys_creat (const char * path
, int mode
)
3917 path
= map_w32_filename (path
, NULL
);
3918 if (w32_unicode_filenames
)
3920 wchar_t path_w
[MAX_PATH
];
3922 filename_to_utf16 (path
, path_w
);
3923 return _wcreat (path_w
, mode
);
3927 char path_a
[MAX_PATH
];
3929 filename_to_ansi (path
, path_a
);
3930 return _creat (path_a
, mode
);
3935 sys_fopen (const char * path
, const char * mode
)
3939 const char * mode_save
= mode
;
3941 /* Force all file handles to be non-inheritable. This is necessary to
3942 ensure child processes don't unwittingly inherit handles that might
3943 prevent future file access. */
3947 else if (mode
[0] == 'w' || mode
[0] == 'a')
3948 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3952 /* Only do simplistic option parsing. */
3956 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3959 else if (mode
[0] == 'b')
3964 else if (mode
[0] == 't')
3971 path
= map_w32_filename (path
, NULL
);
3972 if (w32_unicode_filenames
)
3974 wchar_t path_w
[MAX_PATH
];
3976 filename_to_utf16 (path
, path_w
);
3977 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3981 char path_a
[MAX_PATH
];
3983 filename_to_ansi (path
, path_a
);
3984 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3989 return _fdopen (fd
, mode_save
);
3992 /* This only works on NTFS volumes, but is useful to have. */
3994 sys_link (const char * old
, const char * new)
3998 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3999 wchar_t oldname_w
[MAX_PATH
];
4000 char oldname_a
[MAX_PATH
];
4002 if (old
== NULL
|| new == NULL
)
4008 strcpy (oldname
, map_w32_filename (old
, NULL
));
4009 strcpy (newname
, map_w32_filename (new, NULL
));
4011 if (w32_unicode_filenames
)
4013 filename_to_utf16 (oldname
, oldname_w
);
4014 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
4015 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4019 filename_to_ansi (oldname
, oldname_a
);
4020 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
4021 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
4023 if (fileh
!= INVALID_HANDLE_VALUE
)
4027 /* Confusingly, the "alternate" stream name field does not apply
4028 when restoring a hard link, and instead contains the actual
4029 stream data for the link (ie. the name of the link to create).
4030 The WIN32_STREAM_ID structure before the cStreamName field is
4031 the stream header, which is then immediately followed by the
4035 WIN32_STREAM_ID wid
;
4036 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
4039 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
4040 indicates that flag is unsupported for CP_UTF8, and OTOH says
4041 it is the default anyway. */
4042 wlen
= pMultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
4043 data
.wid
.cStreamName
, MAX_PATH
);
4046 LPVOID context
= NULL
;
4049 data
.wid
.dwStreamId
= BACKUP_LINK
;
4050 data
.wid
.dwStreamAttributes
= 0;
4051 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
4052 data
.wid
.Size
.HighPart
= 0;
4053 data
.wid
.dwStreamNameSize
= 0;
4055 if (BackupWrite (fileh
, (LPBYTE
)&data
,
4056 offsetof (WIN32_STREAM_ID
, cStreamName
)
4057 + data
.wid
.Size
.LowPart
,
4058 &wbytes
, FALSE
, FALSE
, &context
)
4059 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
4066 DWORD err
= GetLastError ();
4071 case ERROR_ACCESS_DENIED
:
4072 /* This is what happens when OLDNAME is a directory,
4073 since Windows doesn't support hard links to
4074 directories. Posix says to set errno to EPERM in
4076 if (w32_unicode_filenames
)
4077 attributes
= GetFileAttributesW (oldname_w
);
4079 attributes
= GetFileAttributesA (oldname_a
);
4080 if (attributes
!= -1
4081 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
4083 else if (attributes
== -1
4084 && is_unc_volume (oldname
)
4085 && unc_volume_file_attributes (oldname
) != -1)
4090 case ERROR_TOO_MANY_LINKS
:
4093 case ERROR_NOT_SAME_DEVICE
:
4103 CloseHandle (fileh
);
4112 sys_mkdir (const char * path
)
4114 path
= map_w32_filename (path
, NULL
);
4116 if (w32_unicode_filenames
)
4118 wchar_t path_w
[MAX_PATH
];
4120 filename_to_utf16 (path
, path_w
);
4121 return _wmkdir (path_w
);
4125 char path_a
[MAX_PATH
];
4127 filename_to_ansi (path
, path_a
);
4128 return _mkdir (path_a
);
4133 sys_open (const char * path
, int oflag
, int mode
)
4135 const char* mpath
= map_w32_filename (path
, NULL
);
4138 if (w32_unicode_filenames
)
4140 wchar_t mpath_w
[MAX_PATH
];
4142 filename_to_utf16 (mpath
, mpath_w
);
4143 /* If possible, try to open file without _O_CREAT, to be able to
4144 write to existing hidden and system files. Force all file
4145 handles to be non-inheritable. */
4146 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4147 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4149 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4153 char mpath_a
[MAX_PATH
];
4155 filename_to_ansi (mpath
, mpath_a
);
4156 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4157 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4159 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4165 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4168 Standard algorithm for generating a temporary file name seems to be
4169 use pid or tid with a letter on the front (in place of the 6 X's)
4170 and cycle through the letters to find a unique name. We extend
4171 that to allow any reasonable character as the first of the 6 X's,
4172 so that the number of simultaneously used temporary files will be
4176 mkostemp (char * template, int flags
)
4180 unsigned uid
= GetCurrentThreadId ();
4181 int save_errno
= errno
;
4182 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4185 if (template == NULL
)
4188 p
= template + strlen (template);
4190 /* replace up to the last 5 X's with uid in decimal */
4191 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4193 p
[0] = '0' + uid
% 10;
4197 if (i
< 0 && p
[0] == 'X')
4202 p
[0] = first_char
[i
];
4203 if ((fd
= sys_open (template,
4204 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4205 S_IRUSR
| S_IWUSR
)) >= 0
4213 while (++i
< sizeof (first_char
));
4216 /* Template is badly formed or else we can't generate a unique name. */
4221 fchmod (int fd
, mode_t mode
)
4227 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4230 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4233 bool have_temp_a
= false;
4235 /* MoveFile on Windows 95 doesn't correctly change the short file name
4236 alias in a number of circumstances (it is not easy to predict when
4237 just by looking at oldname and newname, unfortunately). In these
4238 cases, renaming through a temporary name avoids the problem.
4240 A second problem on Windows 95 is that renaming through a temp name when
4241 newname is uppercase fails (the final long name ends up in
4242 lowercase, although the short alias might be uppercase) UNLESS the
4243 long temp name is not 8.3.
4245 So, on Windows 95 we always rename through a temp name, and we make sure
4246 the temp name has a long extension to ensure correct renaming. */
4248 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4250 /* volume_info is set indirectly by map_w32_filename. */
4251 oldname_dev
= volume_info
.serialnum
;
4253 if (os_subtype
== OS_9X
)
4258 char oldname_a
[MAX_PATH
];
4260 oldname
= map_w32_filename (oldname
, NULL
);
4261 filename_to_ansi (oldname
, oldname_a
);
4262 filename_to_ansi (temp
, temp_a
);
4263 if ((o
= strrchr (oldname_a
, '\\')))
4266 o
= (char *) oldname_a
;
4268 if ((p
= strrchr (temp_a
, '\\')))
4275 /* Force temp name to require a manufactured 8.3 alias - this
4276 seems to make the second rename work properly. */
4277 sprintf (p
, "_.%s.%u", o
, i
);
4279 result
= rename (oldname_a
, temp_a
);
4281 /* This loop must surely terminate! */
4282 while (result
< 0 && errno
== EEXIST
);
4288 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4289 (at least if it is a file; don't do this for directories).
4291 Since we mustn't do this if we are just changing the case of the
4292 file name (we would end up deleting the file we are trying to
4293 rename!), we let rename detect if the destination file already
4294 exists - that way we avoid the possible pitfalls of trying to
4295 determine ourselves whether two names really refer to the same
4296 file, which is not always possible in the general case. (Consider
4297 all the permutations of shared or subst'd drives, etc.) */
4299 newname
= map_w32_filename (newname
, NULL
);
4301 /* volume_info is set indirectly by map_w32_filename. */
4302 newname_dev
= volume_info
.serialnum
;
4304 if (w32_unicode_filenames
)
4306 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4308 filename_to_utf16 (temp
, temp_w
);
4309 filename_to_utf16 (newname
, newname_w
);
4310 result
= _wrename (temp_w
, newname_w
);
4311 if (result
< 0 && force
)
4313 DWORD w32err
= GetLastError ();
4316 && newname_dev
!= oldname_dev
)
4318 /* The implementation of `rename' on Windows does not return
4319 errno = EXDEV when you are moving a directory to a
4320 different storage device (ex. logical disk). It returns
4321 EACCES instead. So here we handle such situations and
4325 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4326 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4329 else if (errno
== EEXIST
)
4331 if (_wchmod (newname_w
, 0666) != 0)
4333 if (_wunlink (newname_w
) != 0)
4335 result
= _wrename (temp_w
, newname_w
);
4337 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4338 && is_symlink (temp
))
4340 /* This is Windows prohibiting the user from creating a
4341 symlink in another place, since that requires
4349 char newname_a
[MAX_PATH
];
4352 filename_to_ansi (temp
, temp_a
);
4353 filename_to_ansi (newname
, newname_a
);
4354 result
= rename (temp_a
, newname_a
);
4355 if (result
< 0 && force
)
4357 DWORD w32err
= GetLastError ();
4360 && newname_dev
!= oldname_dev
)
4364 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4365 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4368 else if (errno
== EEXIST
)
4370 if (_chmod (newname_a
, 0666) != 0)
4372 if (_unlink (newname_a
) != 0)
4374 result
= rename (temp_a
, newname_a
);
4376 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4377 && is_symlink (temp
))
4386 sys_rename (char const *old
, char const *new)
4388 return sys_rename_replace (old
, new, TRUE
);
4392 sys_rmdir (const char * path
)
4394 path
= map_w32_filename (path
, NULL
);
4396 if (w32_unicode_filenames
)
4398 wchar_t path_w
[MAX_PATH
];
4400 filename_to_utf16 (path
, path_w
);
4401 return _wrmdir (path_w
);
4405 char path_a
[MAX_PATH
];
4407 filename_to_ansi (path
, path_a
);
4408 return _rmdir (path_a
);
4413 sys_unlink (const char * path
)
4415 path
= map_w32_filename (path
, NULL
);
4417 if (w32_unicode_filenames
)
4419 wchar_t path_w
[MAX_PATH
];
4421 filename_to_utf16 (path
, path_w
);
4422 /* On Unix, unlink works without write permission. */
4423 _wchmod (path_w
, 0666);
4424 return _wunlink (path_w
);
4428 char path_a
[MAX_PATH
];
4430 filename_to_ansi (path
, path_a
);
4431 _chmod (path_a
, 0666);
4432 return _unlink (path_a
);
4436 static FILETIME utc_base_ft
;
4437 static ULONGLONG utc_base
; /* In 100ns units */
4438 static int init
= 0;
4440 #define FILETIME_TO_U64(result, ft) \
4442 ULARGE_INTEGER uiTemp; \
4443 uiTemp.LowPart = (ft).dwLowDateTime; \
4444 uiTemp.HighPart = (ft).dwHighDateTime; \
4445 result = uiTemp.QuadPart; \
4449 initialize_utc_base (void)
4451 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4460 st
.wMilliseconds
= 0;
4462 SystemTimeToFileTime (&st
, &utc_base_ft
);
4463 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4467 convert_time (FILETIME ft
)
4473 initialize_utc_base ();
4477 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4480 FILETIME_TO_U64 (tmp
, ft
);
4481 return (time_t) ((tmp
- utc_base
) / 10000000L);
4485 convert_from_time_t (time_t time
, FILETIME
* pft
)
4491 initialize_utc_base ();
4495 /* time in 100ns units since 1-Jan-1601 */
4496 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4497 pft
->dwHighDateTime
= tmp
.HighPart
;
4498 pft
->dwLowDateTime
= tmp
.LowPart
;
4501 static PSECURITY_DESCRIPTOR
4502 get_file_security_desc_by_handle (HANDLE h
)
4504 PSECURITY_DESCRIPTOR psd
= NULL
;
4506 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4507 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4509 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4510 NULL
, NULL
, NULL
, NULL
, &psd
);
4511 if (err
!= ERROR_SUCCESS
)
4517 static PSECURITY_DESCRIPTOR
4518 get_file_security_desc_by_name (const char *fname
)
4520 PSECURITY_DESCRIPTOR psd
= NULL
;
4522 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4523 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4525 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4527 err
= GetLastError ();
4528 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4532 psd
= xmalloc (sd_len
);
4533 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4545 unsigned n_subauthorities
;
4547 /* Use the last sub-authority value of the RID, the relative
4548 portion of the SID, as user/group ID. */
4549 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4550 if (n_subauthorities
< 1)
4551 return 0; /* the "World" RID */
4552 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4555 /* Caching SID and account values for faster lokup. */
4559 struct w32_id
*next
;
4561 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4564 static struct w32_id
*w32_idlist
;
4567 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4569 struct w32_id
*tail
, *found
;
4571 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4573 if (equal_sid ((PSID
)tail
->sid
, sid
))
4582 strcpy (name
, found
->name
);
4590 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4593 struct w32_id
*new_entry
;
4595 /* We don't want to leave behind stale cache from when Emacs was
4599 sid_len
= get_length_sid (sid
);
4600 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4603 new_entry
->rid
= id
;
4604 strcpy (new_entry
->name
, name
);
4605 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4606 new_entry
->next
= w32_idlist
;
4607 w32_idlist
= new_entry
;
4616 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4620 SID_NAME_USE ignore
;
4622 DWORD name_len
= sizeof (name
);
4624 DWORD domain_len
= sizeof (domain
);
4629 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4630 else if (what
== GID
)
4631 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4635 if (!result
|| !is_valid_sid (sid
))
4637 else if (!w32_cached_id (sid
, id
, nm
))
4639 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4640 domain
, &domain_len
, &ignore
)
4641 || name_len
> UNLEN
+1)
4645 *id
= get_rid (sid
);
4647 w32_add_to_cache (sid
, *id
, name
);
4654 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4656 int dflt_usr
= 0, dflt_grp
= 0;
4665 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4667 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4670 /* Consider files to belong to current user/group, if we cannot get
4671 more accurate information. */
4674 st
->st_uid
= dflt_passwd
.pw_uid
;
4675 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4679 st
->st_gid
= dflt_passwd
.pw_gid
;
4680 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4684 /* Return non-zero if NAME is a potentially slow filesystem. */
4686 is_slow_fs (const char *name
)
4691 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4692 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4693 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4694 devtype
= GetDriveType (NULL
); /* use root of current drive */
4697 /* GetDriveType needs the root directory of the drive. */
4698 strncpy (drive_root
, name
, 2);
4699 drive_root
[2] = '\\';
4700 drive_root
[3] = '\0';
4701 devtype
= GetDriveType (drive_root
);
4703 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4706 /* If this is non-zero, the caller wants accurate information about
4707 file's owner and group, which could be expensive to get. dired.c
4708 uses this flag when needed for the job at hand. */
4709 int w32_stat_get_owner_group
;
4711 /* MSVC stat function can't cope with UNC names and has other bugs, so
4712 replace it with our own. This also allows us to calculate consistent
4713 inode values and owner/group without hacks in the main Emacs code,
4714 and support file names encoded in UTF-8. */
4717 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4719 char *name
, *save_name
, *r
;
4720 WIN32_FIND_DATAW wfd_w
;
4721 WIN32_FIND_DATAA wfd_a
;
4723 unsigned __int64 fake_inode
= 0;
4726 int rootdir
= FALSE
;
4727 PSECURITY_DESCRIPTOR psd
= NULL
;
4728 int is_a_symlink
= 0;
4729 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4730 DWORD access_rights
= 0;
4731 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4732 FILETIME ctime
, atime
, wtime
;
4733 wchar_t name_w
[MAX_PATH
];
4734 char name_a
[MAX_PATH
];
4736 if (path
== NULL
|| buf
== NULL
)
4742 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4743 /* Must be valid filename, no wild cards or other invalid
4745 if (strpbrk (name
, "*?|<>\""))
4751 len
= strlen (name
);
4752 /* Allocate 1 extra byte so that we could append a slash to a root
4753 directory, down below. */
4754 name
= strcpy (alloca (len
+ 2), name
);
4756 /* Avoid a somewhat costly call to is_symlink if the filesystem
4757 doesn't support symlinks. */
4758 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4759 is_a_symlink
= is_symlink (name
);
4761 /* Plan A: Open the file and get all the necessary information via
4762 the resulting handle. This solves several issues in one blow:
4764 . retrieves attributes for the target of a symlink, if needed
4765 . gets attributes of root directories and symlinks pointing to
4766 root directories, thus avoiding the need for special-casing
4767 these and detecting them by examining the file-name format
4768 . retrieves more accurate attributes (e.g., non-zero size for
4769 some directories, esp. directories that are junction points)
4770 . correctly resolves "c:/..", "/.." and similar file names
4771 . avoids run-time penalties for 99% of use cases
4773 Plan A is always tried first, unless the user asked not to (but
4774 if the file is a symlink and we need to follow links, we try Plan
4775 A even if the user asked not to).
4777 If Plan A fails, we go to Plan B (below), where various
4778 potentially expensive techniques must be used to handle "special"
4779 files such as UNC volumes etc. */
4780 if (!(NILP (Vw32_get_true_file_attributes
)
4781 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4782 /* Following symlinks requires getting the info by handle. */
4783 || (is_a_symlink
&& follow_symlinks
))
4785 BY_HANDLE_FILE_INFORMATION info
;
4787 if (is_a_symlink
&& !follow_symlinks
)
4788 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4789 /* READ_CONTROL access rights are required to get security info
4790 by handle. But if the OS doesn't support security in the
4791 first place, we don't need to try. */
4792 if (is_windows_9x () != TRUE
)
4793 access_rights
|= READ_CONTROL
;
4795 if (w32_unicode_filenames
)
4797 filename_to_utf16 (name
, name_w
);
4798 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4800 /* If CreateFile fails with READ_CONTROL, try again with
4801 zero as access rights. */
4802 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4803 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4808 filename_to_ansi (name
, name_a
);
4809 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4811 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4812 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4815 if (fh
== INVALID_HANDLE_VALUE
)
4816 goto no_true_file_attributes
;
4818 /* This is more accurate in terms of getting the correct number
4819 of links, but is quite slow (it is noticeable when Emacs is
4820 making a list of file name completions). */
4821 if (GetFileInformationByHandle (fh
, &info
))
4823 nlinks
= info
.nNumberOfLinks
;
4824 /* Might as well use file index to fake inode values, but this
4825 is not guaranteed to be unique unless we keep a handle open
4826 all the time (even then there are situations where it is
4827 not unique). Reputedly, there are at most 48 bits of info
4828 (on NTFS, presumably less on FAT). */
4829 fake_inode
= info
.nFileIndexHigh
;
4831 fake_inode
+= info
.nFileIndexLow
;
4832 serialnum
= info
.dwVolumeSerialNumber
;
4833 fs_high
= info
.nFileSizeHigh
;
4834 fs_low
= info
.nFileSizeLow
;
4835 ctime
= info
.ftCreationTime
;
4836 atime
= info
.ftLastAccessTime
;
4837 wtime
= info
.ftLastWriteTime
;
4838 fattrs
= info
.dwFileAttributes
;
4842 /* We don't go to Plan B here, because it's not clear that
4843 it's a good idea. The only known use case where
4844 CreateFile succeeds, but GetFileInformationByHandle fails
4845 (with ERROR_INVALID_FUNCTION) is for character devices
4846 such as NUL, PRN, etc. For these, switching to Plan B is
4847 a net loss, because we lose the character device
4848 attribute returned by GetFileType below (FindFirstFile
4849 doesn't set that bit in the attributes), and the other
4850 fields don't make sense for character devices anyway.
4851 Emacs doesn't really care for non-file entities in the
4852 context of l?stat, so neither do we. */
4854 /* w32err is assigned so one could put a breakpoint here and
4855 examine its value, when GetFileInformationByHandle
4857 DWORD w32err
= GetLastError ();
4861 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4867 /* Test for a symlink before testing for a directory, since
4868 symlinks to directories have the directory bit set, but we
4869 don't want them to appear as directories. */
4870 if (is_a_symlink
&& !follow_symlinks
)
4871 buf
->st_mode
= S_IFLNK
;
4872 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4873 buf
->st_mode
= S_IFDIR
;
4876 DWORD ftype
= GetFileType (fh
);
4880 case FILE_TYPE_DISK
:
4881 buf
->st_mode
= S_IFREG
;
4883 case FILE_TYPE_PIPE
:
4884 buf
->st_mode
= S_IFIFO
;
4886 case FILE_TYPE_CHAR
:
4887 case FILE_TYPE_UNKNOWN
:
4889 buf
->st_mode
= S_IFCHR
;
4892 /* We produce the fallback owner and group data, based on the
4893 current user that runs Emacs, in the following cases:
4895 . caller didn't request owner and group info
4896 . this is Windows 9X
4897 . getting security by handle failed, and we need to produce
4898 information for the target of a symlink (this is better
4899 than producing a potentially misleading info about the
4902 If getting security by handle fails, and we don't need to
4903 resolve symlinks, we try getting security by name. */
4904 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4905 get_file_owner_and_group (NULL
, buf
);
4908 psd
= get_file_security_desc_by_handle (fh
);
4911 get_file_owner_and_group (psd
, buf
);
4914 else if (!(is_a_symlink
&& follow_symlinks
))
4916 psd
= get_file_security_desc_by_name (name
);
4917 get_file_owner_and_group (psd
, buf
);
4921 get_file_owner_and_group (NULL
, buf
);
4927 no_true_file_attributes
:
4928 /* Plan B: Either getting a handle on the file failed, or the
4929 caller explicitly asked us to not bother making this
4930 information more accurate.
4932 Implementation note: In Plan B, we never bother to resolve
4933 symlinks, even if we got here because we tried Plan A and
4934 failed. That's because, even if the caller asked for extra
4935 precision by setting Vw32_get_true_file_attributes to t,
4936 resolving symlinks requires acquiring a file handle to the
4937 symlink, which we already know will fail. And if the user
4938 did not ask for extra precision, resolving symlinks will fly
4939 in the face of that request, since the user then wants the
4940 lightweight version of the code. */
4941 rootdir
= (path
>= save_name
+ len
- 1
4942 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4944 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4945 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4946 if (IS_DIRECTORY_SEP (r
[0])
4947 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4950 /* Note: If NAME is a symlink to the root of a UNC volume
4951 (i.e. "\\SERVER"), we will not detect that here, and we will
4952 return data about the symlink as result of FindFirst below.
4953 This is unfortunate, but that marginal use case does not
4954 justify a call to chase_symlinks which would impose a penalty
4955 on all the other use cases. (We get here for symlinks to
4956 roots of UNC volumes because CreateFile above fails for them,
4957 unlike with symlinks to root directories X:\ of drives.) */
4958 if (is_unc_volume (name
))
4960 fattrs
= unc_volume_file_attributes (name
);
4964 ctime
= atime
= wtime
= utc_base_ft
;
4968 /* Make sure root directories end in a slash. */
4969 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4970 strcat (name
, "\\");
4971 if (GetDriveType (name
) < 2)
4977 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4978 ctime
= atime
= wtime
= utc_base_ft
;
4984 /* Make sure non-root directories do NOT end in a slash,
4985 otherwise FindFirstFile might fail. */
4986 if (IS_DIRECTORY_SEP (name
[len
-1]))
4989 /* (This is hacky, but helps when doing file completions on
4990 network drives.) Optimize by using information available from
4991 active readdir if possible. */
4992 len
= strlen (dir_pathname
);
4993 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4995 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4996 && last_dir_find_data
!= -1
4997 && !(is_a_symlink
&& follow_symlinks
)
4998 /* The 2 file-name comparisons below support only ASCII
4999 characters, and will lose (compare not equal) when
5000 the file names include non-ASCII characters that are
5001 the same but for the case. However, doing this
5002 properly involves: (a) converting both file names to
5003 UTF-16, (b) lower-casing both names using CharLowerW,
5004 and (c) comparing the results; this would be quite a
5005 bit slower, whereas Plan B is for users who want
5006 lightweight albeit inaccurate version of 'stat'. */
5007 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
5008 && IS_DIRECTORY_SEP (name
[len
])
5009 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
5011 have_wfd
= last_dir_find_data
;
5012 /* This was the last entry returned by readdir. */
5013 if (last_dir_find_data
== DIR_FIND_DATA_W
)
5014 wfd_w
= dir_find_data_w
;
5016 wfd_a
= dir_find_data_a
;
5020 logon_network_drive (name
);
5022 if (w32_unicode_filenames
)
5024 filename_to_utf16 (name
, name_w
);
5025 fh
= FindFirstFileW (name_w
, &wfd_w
);
5026 have_wfd
= DIR_FIND_DATA_W
;
5030 filename_to_ansi (name
, name_a
);
5031 /* If NAME includes characters not representable by
5032 the current ANSI codepage, filename_to_ansi
5033 usually replaces them with a '?'. We don't want
5034 to let FindFirstFileA interpret those as wildcards,
5035 and "succeed", returning us data from some random
5036 file in the same directory. */
5037 if (_mbspbrk (name_a
, "?"))
5038 fh
= INVALID_HANDLE_VALUE
;
5040 fh
= FindFirstFileA (name_a
, &wfd_a
);
5041 have_wfd
= DIR_FIND_DATA_A
;
5043 if (fh
== INVALID_HANDLE_VALUE
)
5050 /* Note: if NAME is a symlink, the information we get from
5051 FindFirstFile is for the symlink, not its target. */
5052 if (have_wfd
== DIR_FIND_DATA_W
)
5054 fattrs
= wfd_w
.dwFileAttributes
;
5055 ctime
= wfd_w
.ftCreationTime
;
5056 atime
= wfd_w
.ftLastAccessTime
;
5057 wtime
= wfd_w
.ftLastWriteTime
;
5058 fs_high
= wfd_w
.nFileSizeHigh
;
5059 fs_low
= wfd_w
.nFileSizeLow
;
5063 fattrs
= wfd_a
.dwFileAttributes
;
5064 ctime
= wfd_a
.ftCreationTime
;
5065 atime
= wfd_a
.ftLastAccessTime
;
5066 wtime
= wfd_a
.ftLastWriteTime
;
5067 fs_high
= wfd_a
.nFileSizeHigh
;
5068 fs_low
= wfd_a
.nFileSizeLow
;
5072 serialnum
= volume_info
.serialnum
;
5074 if (is_a_symlink
&& !follow_symlinks
)
5075 buf
->st_mode
= S_IFLNK
;
5076 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5077 buf
->st_mode
= S_IFDIR
;
5079 buf
->st_mode
= S_IFREG
;
5081 get_file_owner_and_group (NULL
, buf
);
5084 buf
->st_ino
= fake_inode
;
5086 buf
->st_dev
= serialnum
;
5087 buf
->st_rdev
= serialnum
;
5089 buf
->st_size
= fs_high
;
5090 buf
->st_size
<<= 32;
5091 buf
->st_size
+= fs_low
;
5092 buf
->st_nlink
= nlinks
;
5094 /* Convert timestamps to Unix format. */
5095 buf
->st_mtime
= convert_time (wtime
);
5096 buf
->st_atime
= convert_time (atime
);
5097 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5098 buf
->st_ctime
= convert_time (ctime
);
5099 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5101 /* determine rwx permissions */
5102 if (is_a_symlink
&& !follow_symlinks
)
5103 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5106 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5107 permission
= S_IREAD
;
5109 permission
= S_IREAD
| S_IWRITE
;
5111 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5112 permission
|= S_IEXEC
;
5113 else if (is_exec (name
))
5114 permission
|= S_IEXEC
;
5117 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5123 stat (const char * path
, struct stat
* buf
)
5125 return stat_worker (path
, buf
, 1);
5129 lstat (const char * path
, struct stat
* buf
)
5131 return stat_worker (path
, buf
, 0);
5135 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5137 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5138 This is good enough for the current usage in Emacs, but is fragile.
5140 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5141 Gnulib does this and can serve as a model. */
5142 char fullname
[MAX_UTF8_PATH
];
5146 char lastc
= dir_pathname
[strlen (dir_pathname
) - 1];
5148 if (_snprintf (fullname
, sizeof fullname
, "%s%s%s",
5149 dir_pathname
, IS_DIRECTORY_SEP (lastc
) ? "" : "/", name
)
5152 errno
= ENAMETOOLONG
;
5158 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5161 /* Provide fstat and utime as well as stat for consistent handling of
5164 fstat (int desc
, struct stat
* buf
)
5166 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5167 BY_HANDLE_FILE_INFORMATION info
;
5168 unsigned __int64 fake_inode
;
5171 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5173 case FILE_TYPE_DISK
:
5174 buf
->st_mode
= S_IFREG
;
5175 if (!GetFileInformationByHandle (fh
, &info
))
5181 case FILE_TYPE_PIPE
:
5182 buf
->st_mode
= S_IFIFO
;
5184 case FILE_TYPE_CHAR
:
5185 case FILE_TYPE_UNKNOWN
:
5187 buf
->st_mode
= S_IFCHR
;
5189 memset (&info
, 0, sizeof (info
));
5190 info
.dwFileAttributes
= 0;
5191 info
.ftCreationTime
= utc_base_ft
;
5192 info
.ftLastAccessTime
= utc_base_ft
;
5193 info
.ftLastWriteTime
= utc_base_ft
;
5196 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5197 buf
->st_mode
= S_IFDIR
;
5199 buf
->st_nlink
= info
.nNumberOfLinks
;
5200 /* Might as well use file index to fake inode values, but this
5201 is not guaranteed to be unique unless we keep a handle open
5202 all the time (even then there are situations where it is
5203 not unique). Reputedly, there are at most 48 bits of info
5204 (on NTFS, presumably less on FAT). */
5205 fake_inode
= info
.nFileIndexHigh
;
5207 fake_inode
+= info
.nFileIndexLow
;
5209 /* MSVC defines _ino_t to be short; other libc's might not. */
5210 if (sizeof (buf
->st_ino
) == 2)
5211 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5213 buf
->st_ino
= fake_inode
;
5215 /* If the caller so requested, get the true file owner and group.
5216 Otherwise, consider the file to belong to the current user. */
5217 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5218 get_file_owner_and_group (NULL
, buf
);
5221 PSECURITY_DESCRIPTOR psd
= NULL
;
5223 psd
= get_file_security_desc_by_handle (fh
);
5226 get_file_owner_and_group (psd
, buf
);
5230 get_file_owner_and_group (NULL
, buf
);
5233 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5234 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5236 buf
->st_size
= info
.nFileSizeHigh
;
5237 buf
->st_size
<<= 32;
5238 buf
->st_size
+= info
.nFileSizeLow
;
5240 /* Convert timestamps to Unix format. */
5241 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5242 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5243 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5244 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5245 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5247 /* determine rwx permissions */
5248 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5249 permission
= S_IREAD
;
5251 permission
= S_IREAD
| S_IWRITE
;
5253 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5254 permission
|= S_IEXEC
;
5257 #if 0 /* no way of knowing the filename */
5258 char * p
= strrchr (name
, '.');
5260 (xstrcasecmp (p
, ".exe") == 0 ||
5261 xstrcasecmp (p
, ".com") == 0 ||
5262 xstrcasecmp (p
, ".bat") == 0 ||
5263 xstrcasecmp (p
, ".cmd") == 0))
5264 permission
|= S_IEXEC
;
5268 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5273 /* A version of 'utime' which handles directories as well as
5277 utime (const char *name
, struct utimbuf
*times
)
5279 struct utimbuf deftime
;
5286 deftime
.modtime
= deftime
.actime
= time (NULL
);
5290 if (w32_unicode_filenames
)
5292 wchar_t name_utf16
[MAX_PATH
];
5294 if (filename_to_utf16 (name
, name_utf16
) != 0)
5295 return -1; /* errno set by filename_to_utf16 */
5297 /* Need write access to set times. */
5298 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5299 /* If NAME specifies a directory, FILE_SHARE_DELETE
5300 allows other processes to delete files inside it,
5301 while we have the directory open. */
5302 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5303 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5307 char name_ansi
[MAX_PATH
];
5309 if (filename_to_ansi (name
, name_ansi
) != 0)
5310 return -1; /* errno set by filename_to_ansi */
5312 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5313 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5314 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5316 if (fh
!= INVALID_HANDLE_VALUE
)
5318 convert_from_time_t (times
->actime
, &atime
);
5319 convert_from_time_t (times
->modtime
, &mtime
);
5320 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5330 DWORD err
= GetLastError ();
5334 case ERROR_FILE_NOT_FOUND
:
5335 case ERROR_PATH_NOT_FOUND
:
5336 case ERROR_INVALID_DRIVE
:
5337 case ERROR_BAD_NETPATH
:
5338 case ERROR_DEV_NOT_EXIST
:
5339 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5340 file name includes ?s, i.e. translation to ANSI failed. */
5341 case ERROR_INVALID_NAME
:
5344 case ERROR_TOO_MANY_OPEN_FILES
:
5347 case ERROR_ACCESS_DENIED
:
5348 case ERROR_SHARING_VIOLATION
:
5361 sys_umask (int mode
)
5363 static int current_mask
;
5364 int retval
, arg
= 0;
5366 /* The only bit we really support is the write bit. Files are
5367 always readable on MS-Windows, and the execute bit does not exist
5369 /* FIXME: if the GROUP and OTHER bits are reset, we should use ACLs
5370 to prevent access by other users on NTFS. */
5371 if ((mode
& S_IWRITE
) != 0)
5374 retval
= _umask (arg
);
5375 /* Merge into the return value the bits they've set the last time,
5376 which msvcrt.dll ignores and never returns. Emacs insists on its
5377 notion of mask being identical to what we return. */
5378 retval
|= (current_mask
& ~S_IWRITE
);
5379 current_mask
= mode
;
5385 /* Symlink-related functions. */
5386 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5387 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5391 symlink (char const *filename
, char const *linkname
)
5393 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5395 int dir_access
, filename_ends_in_slash
;
5397 /* Diagnostics follows Posix as much as possible. */
5398 if (filename
== NULL
|| linkname
== NULL
)
5408 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5410 errno
= ENAMETOOLONG
;
5414 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5415 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5421 /* Note: since empty FILENAME was already rejected, we can safely
5422 refer to FILENAME[1]. */
5423 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5425 /* Non-absolute FILENAME is understood as being relative to
5426 LINKNAME's directory. We need to prepend that directory to
5427 FILENAME to get correct results from faccessat below, since
5428 otherwise it will interpret FILENAME relative to the
5429 directory where the Emacs process runs. Note that
5430 make-symbolic-link always makes sure LINKNAME is a fully
5431 expanded file name. */
5432 char tem
[MAX_UTF8_PATH
];
5433 char *p
= linkfn
+ strlen (linkfn
);
5435 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5438 strncpy (tem
, linkfn
, p
- linkfn
);
5439 tem
[p
- linkfn
] = '\0';
5440 strcat (tem
, filename
);
5441 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5444 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5446 /* Since Windows distinguishes between symlinks to directories and
5447 to files, we provide a kludgy feature: if FILENAME doesn't
5448 exist, but ends in a slash, we create a symlink to directory. If
5449 FILENAME exists and is a directory, we always create a symlink to
5451 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5452 if (dir_access
== 0 || filename_ends_in_slash
)
5453 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5455 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5456 if (filename_ends_in_slash
)
5457 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5460 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5462 /* ENOSYS is set by create_symbolic_link, when it detects that
5463 the OS doesn't support the CreateSymbolicLink API. */
5464 if (errno
!= ENOSYS
)
5466 DWORD w32err
= GetLastError ();
5470 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5471 TGTFN point to the same file name, go figure. */
5473 case ERROR_FILE_EXISTS
:
5476 case ERROR_ACCESS_DENIED
:
5479 case ERROR_FILE_NOT_FOUND
:
5480 case ERROR_PATH_NOT_FOUND
:
5481 case ERROR_BAD_NETPATH
:
5482 case ERROR_INVALID_REPARSE_DATA
:
5485 case ERROR_DIRECTORY
:
5488 case ERROR_PRIVILEGE_NOT_HELD
:
5489 case ERROR_NOT_ALL_ASSIGNED
:
5492 case ERROR_DISK_FULL
:
5505 /* A quick inexpensive test of whether FILENAME identifies a file that
5506 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5507 must already be in the normalized form returned by
5510 Note: for repeated operations on many files, it is best to test
5511 whether the underlying volume actually supports symlinks, by
5512 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5513 avoid the call to this function if it doesn't. That's because the
5514 call to GetFileAttributes takes a non-negligible time, especially
5515 on non-local or removable filesystems. See stat_worker for an
5516 example of how to do that. */
5518 is_symlink (const char *filename
)
5521 wchar_t filename_w
[MAX_PATH
];
5522 char filename_a
[MAX_PATH
];
5523 WIN32_FIND_DATAW wfdw
;
5524 WIN32_FIND_DATAA wfda
;
5526 int attrs_mean_symlink
;
5528 if (w32_unicode_filenames
)
5530 filename_to_utf16 (filename
, filename_w
);
5531 attrs
= GetFileAttributesW (filename_w
);
5535 filename_to_ansi (filename
, filename_a
);
5536 attrs
= GetFileAttributesA (filename_a
);
5540 DWORD w32err
= GetLastError ();
5544 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5546 case ERROR_ACCESS_DENIED
:
5549 case ERROR_FILE_NOT_FOUND
:
5550 case ERROR_PATH_NOT_FOUND
:
5557 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5559 logon_network_drive (filename
);
5560 if (w32_unicode_filenames
)
5562 fh
= FindFirstFileW (filename_w
, &wfdw
);
5563 attrs_mean_symlink
=
5564 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5565 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5567 else if (_mbspbrk (filename_a
, "?"))
5569 /* filename_to_ansi failed to convert the file name. */
5575 fh
= FindFirstFileA (filename_a
, &wfda
);
5576 attrs_mean_symlink
=
5577 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5578 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5580 if (fh
== INVALID_HANDLE_VALUE
)
5583 return attrs_mean_symlink
;
5586 /* If NAME identifies a symbolic link, copy into BUF the file name of
5587 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5588 null-terminate the target name, even if it fits. Return the number
5589 of bytes copied, or -1 if NAME is not a symlink or any error was
5590 encountered while resolving it. The file name copied into BUF is
5591 encoded in the current ANSI codepage. */
5593 readlink (const char *name
, char *buf
, size_t buf_size
)
5596 TOKEN_PRIVILEGES privs
;
5597 int restore_privs
= 0;
5600 char resolved
[MAX_UTF8_PATH
];
5613 path
= map_w32_filename (name
, NULL
);
5615 if (strlen (path
) > MAX_UTF8_PATH
)
5617 errno
= ENAMETOOLONG
;
5622 if (is_windows_9x () == TRUE
5623 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5624 || !is_symlink (path
))
5627 errno
= EINVAL
; /* not a symlink */
5631 /* Done with simple tests, now we're in for some _real_ work. */
5632 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5634 /* Implementation note: From here and onward, don't return early,
5635 since that will fail to restore the original set of privileges of
5636 the calling thread. */
5638 retval
= -1; /* not too optimistic, are we? */
5640 /* Note: In the next call to CreateFile, we use zero as the 2nd
5641 argument because, when the symlink is a hidden/system file,
5642 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5643 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5644 and directory symlinks. */
5645 if (w32_unicode_filenames
)
5647 wchar_t path_w
[MAX_PATH
];
5649 filename_to_utf16 (path
, path_w
);
5650 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5651 FILE_FLAG_OPEN_REPARSE_POINT
5652 | FILE_FLAG_BACKUP_SEMANTICS
,
5657 char path_a
[MAX_PATH
];
5659 filename_to_ansi (path
, path_a
);
5660 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5661 FILE_FLAG_OPEN_REPARSE_POINT
5662 | FILE_FLAG_BACKUP_SEMANTICS
,
5665 if (sh
!= INVALID_HANDLE_VALUE
)
5667 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5668 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5671 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5672 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5675 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5679 /* Copy the link target name, in wide characters, from
5680 reparse_data, then convert it to multibyte encoding in
5681 the current locale's codepage. */
5685 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5687 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5688 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5689 size_t size_to_copy
= buf_size
;
5691 /* According to MSDN, PrintNameLength does not include the
5692 terminating null character. */
5693 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5694 memcpy (lwname
, lwname_src
, lwname_len
);
5695 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5696 filename_from_utf16 (lwname
, resolved
);
5697 dostounix_filename (resolved
);
5698 lname_size
= strlen (resolved
) + 1;
5699 if (lname_size
<= buf_size
)
5700 size_to_copy
= lname_size
;
5701 strncpy (buf
, resolved
, size_to_copy
);
5703 retval
= size_to_copy
;
5709 /* CreateFile failed. */
5710 DWORD w32err2
= GetLastError ();
5714 case ERROR_FILE_NOT_FOUND
:
5715 case ERROR_PATH_NOT_FOUND
:
5718 case ERROR_ACCESS_DENIED
:
5719 case ERROR_TOO_MANY_OPEN_FILES
:
5729 restore_privilege (&privs
);
5737 readlinkat (int fd
, char const *name
, char *buffer
,
5740 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5741 as in fstatat. FIXME: Add proper support for readlinkat. */
5742 char fullname
[MAX_UTF8_PATH
];
5746 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5749 errno
= ENAMETOOLONG
;
5755 return readlink (name
, buffer
, buffer_size
);
5758 /* If FILE is a symlink, return its target (stored in a static
5759 buffer); otherwise return FILE.
5761 This function repeatedly resolves symlinks in the last component of
5762 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5763 until it arrives at a file whose last component is not a symlink,
5764 or some error occurs. It returns the target of the last
5765 successfully resolved symlink in the chain. If it succeeds to
5766 resolve even a single symlink, the value returned is an absolute
5767 file name with backslashes (result of GetFullPathName). By
5768 contrast, if the original FILE is returned, it is unaltered.
5770 Note: This function can set errno even if it succeeds.
5772 Implementation note: we only resolve the last portion ("basename")
5773 of the argument FILE and of each following file in the chain,
5774 disregarding any possible symlinks in its leading directories.
5775 This is because Windows system calls and library functions
5776 transparently resolve symlinks in leading directories and return
5777 correct information, as long as the basename is not a symlink. */
5779 chase_symlinks (const char *file
)
5781 static char target
[MAX_UTF8_PATH
];
5782 char link
[MAX_UTF8_PATH
];
5783 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5784 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5785 ssize_t res
, link_len
;
5788 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5789 return (char *)file
;
5791 if (w32_unicode_filenames
)
5793 wchar_t file_w
[MAX_PATH
];
5795 filename_to_utf16 (file
, file_w
);
5796 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5797 return (char *)file
;
5798 filename_from_utf16 (link_w
, link
);
5802 char file_a
[MAX_PATH
];
5804 filename_to_ansi (file
, file_a
);
5805 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5806 return (char *)file
;
5807 filename_from_ansi (link_a
, link
);
5809 link_len
= strlen (link
);
5814 /* Remove trailing slashes, as we want to resolve the last
5815 non-trivial part of the link name. */
5816 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5817 link
[link_len
--] = '\0';
5819 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5823 if (!(IS_DEVICE_SEP (target
[1])
5824 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5826 /* Target is relative. Append it to the directory part of
5827 the symlink, then copy the result back to target. */
5828 char *p
= link
+ link_len
;
5830 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5833 strcpy (target
, link
);
5835 /* Resolve any "." and ".." to get a fully-qualified file name
5837 if (w32_unicode_filenames
)
5839 filename_to_utf16 (target
, target_w
);
5840 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5842 filename_from_utf16 (link_w
, link
);
5846 filename_to_ansi (target
, target_a
);
5847 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5849 filename_from_ansi (link_a
, link
);
5851 link_len
= strlen (link
);
5853 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5855 if (loop_count
> 100)
5858 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5859 return (char *)file
;
5864 /* Posix ACL emulation. */
5867 acl_valid (acl_t acl
)
5869 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5873 acl_to_text (acl_t acl
, ssize_t
*size
)
5876 SECURITY_INFORMATION flags
=
5877 OWNER_SECURITY_INFORMATION
|
5878 GROUP_SECURITY_INFORMATION
|
5879 DACL_SECURITY_INFORMATION
;
5880 char *retval
= NULL
;
5886 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5889 /* We don't want to mix heaps, so we duplicate the string in our
5890 heap and free the one allocated by the API. */
5891 retval
= xstrdup (str_acl
);
5894 LocalFree (str_acl
);
5896 else if (errno
!= ENOTSUP
)
5903 acl_from_text (const char *acl_str
)
5905 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5911 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5914 retval
= xmalloc (sd_size
);
5915 memcpy (retval
, psd
, sd_size
);
5918 else if (errno
!= ENOTSUP
)
5925 acl_free (void *ptr
)
5932 acl_get_file (const char *fname
, acl_type_t type
)
5934 PSECURITY_DESCRIPTOR psd
= NULL
;
5935 const char *filename
;
5937 if (type
== ACL_TYPE_ACCESS
)
5940 SECURITY_INFORMATION si
=
5941 OWNER_SECURITY_INFORMATION
|
5942 GROUP_SECURITY_INFORMATION
|
5943 DACL_SECURITY_INFORMATION
;
5946 filename
= map_w32_filename (fname
, NULL
);
5947 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5948 fname
= chase_symlinks (filename
);
5953 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5954 && errno
!= ENOTSUP
)
5956 err
= GetLastError ();
5957 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5959 psd
= xmalloc (sd_len
);
5960 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5967 else if (err
== ERROR_FILE_NOT_FOUND
5968 || err
== ERROR_PATH_NOT_FOUND
5969 /* ERROR_INVALID_NAME is what we get if
5970 w32-unicode-filenames is nil and the file cannot
5971 be encoded in the current ANSI codepage. */
5972 || err
== ERROR_INVALID_NAME
)
5980 else if (type
!= ACL_TYPE_DEFAULT
)
5987 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5989 TOKEN_PRIVILEGES old1
, old2
;
5991 int st
= 0, retval
= -1;
5992 SECURITY_INFORMATION flags
= 0;
5993 PSID psidOwner
, psidGroup
;
5998 const char *filename
;
6000 if (acl_valid (acl
) != 0
6001 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
6007 if (type
== ACL_TYPE_DEFAULT
)
6013 filename
= map_w32_filename (fname
, NULL
);
6014 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
6015 fname
= chase_symlinks (filename
);
6019 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psidOwner
,
6022 flags
|= OWNER_SECURITY_INFORMATION
;
6023 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psidGroup
,
6026 flags
|= GROUP_SECURITY_INFORMATION
;
6027 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
6030 flags
|= DACL_SECURITY_INFORMATION
;
6034 /* According to KB-245153, setting the owner will succeed if either:
6035 (1) the caller is the user who will be the new owner, and has the
6036 SE_TAKE_OWNERSHIP privilege, or
6037 (2) the caller has the SE_RESTORE privilege, in which case she can
6038 set any valid user or group as the owner
6040 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
6041 privileges, and disregard any failures in obtaining them. If
6042 these privileges cannot be obtained, and do not already exist in
6043 the calling thread's security token, this function could fail
6045 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
6047 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
6052 /* SetFileSecurity is deprecated by MS, and sometimes fails when
6053 DACL inheritance is involved, but it seems to preserve ownership
6054 better than SetNamedSecurityInfo, which is important e.g., in
6056 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
6058 err
= GetLastError ();
6060 if (errno
!= ENOTSUP
)
6061 err
= set_named_security_info (fname
, SE_FILE_OBJECT
, flags
,
6062 psidOwner
, psidGroup
, pacl
, NULL
);
6065 err
= ERROR_SUCCESS
;
6066 if (err
!= ERROR_SUCCESS
)
6068 if (errno
== ENOTSUP
)
6070 else if (err
== ERROR_INVALID_OWNER
6071 || err
== ERROR_NOT_ALL_ASSIGNED
6072 || err
== ERROR_ACCESS_DENIED
)
6074 /* Maybe the requested ACL and the one the file already has
6075 are identical, in which case we can silently ignore the
6076 failure. (And no, Windows doesn't.) */
6077 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
6082 char *acl_from
= acl_to_text (current_acl
, NULL
);
6083 char *acl_to
= acl_to_text (acl
, NULL
);
6085 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
6091 acl_free (acl_from
);
6094 acl_free (current_acl
);
6097 else if (err
== ERROR_FILE_NOT_FOUND
6098 || err
== ERROR_PATH_NOT_FOUND
6099 /* ERROR_INVALID_NAME is what we get if
6100 w32-unicode-filenames is nil and the file cannot be
6101 encoded in the current ANSI codepage. */
6102 || err
== ERROR_INVALID_NAME
)
6116 restore_privilege (&old2
);
6117 restore_privilege (&old1
);
6125 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
6126 have a fixed max size for file names, so we don't need the kind of
6127 alloc/malloc/realloc dance the gnulib version does. We also don't
6128 support FD-relative symlinks. */
6130 careadlinkat (int fd
, char const *filename
,
6131 char *buffer
, size_t buffer_size
,
6132 struct allocator
const *alloc
,
6133 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6135 char linkname
[MAX_UTF8_PATH
];
6138 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6142 char *retval
= buffer
;
6144 linkname
[link_size
++] = '\0';
6145 if (link_size
> buffer_size
)
6146 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6148 memcpy (retval
, linkname
, link_size
);
6156 w32_copy_file (const char *from
, const char *to
,
6157 int keep_time
, int preserve_ownership
, int copy_acls
)
6161 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6162 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6164 /* We ignore preserve_ownership for now. */
6165 preserve_ownership
= preserve_ownership
;
6169 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6170 if (acl
== NULL
&& acl_errno_valid (errno
))
6173 if (w32_unicode_filenames
)
6175 filename_to_utf16 (from
, from_w
);
6176 filename_to_utf16 (to
, to_w
);
6177 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6181 filename_to_ansi (from
, from_a
);
6182 filename_to_ansi (to
, to_a
);
6183 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6187 /* CopyFile doesn't set errno when it fails. By far the most
6188 "popular" reason is that the target is read-only. */
6189 DWORD err
= GetLastError ();
6193 case ERROR_FILE_NOT_FOUND
:
6196 case ERROR_ACCESS_DENIED
:
6199 case ERROR_ENCRYPTION_FAILED
:
6211 /* CopyFile retains the timestamp by default. However, see
6212 "Community Additions" for CopyFile: it sounds like that is not
6213 entirely true. Testing on Windows XP confirms that modified time
6214 is copied, but creation and last-access times are not.
6216 else if (!keep_time
)
6218 struct timespec now
;
6221 if (w32_unicode_filenames
)
6223 /* Ensure file is writable while its times are set. */
6224 attributes
= GetFileAttributesW (to_w
);
6225 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6226 now
= current_timespec ();
6227 if (set_file_times (-1, to
, now
, now
))
6229 /* Restore original attributes. */
6230 SetFileAttributesW (to_w
, attributes
);
6235 /* Restore original attributes. */
6236 SetFileAttributesW (to_w
, attributes
);
6240 attributes
= GetFileAttributesA (to_a
);
6241 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6242 now
= current_timespec ();
6243 if (set_file_times (-1, to
, now
, now
))
6245 SetFileAttributesA (to_a
, attributes
);
6250 SetFileAttributesA (to_a
, attributes
);
6256 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6258 if (fail
&& acl_errno_valid (errno
))
6266 /* Support for browsing other processes and their attributes. See
6267 process.c for the Lisp bindings. */
6269 /* Helper wrapper functions. */
6271 static HANDLE WINAPI
6272 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6274 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6276 if (g_b_init_create_toolhelp32_snapshot
== 0)
6278 g_b_init_create_toolhelp32_snapshot
= 1;
6279 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6280 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6281 "CreateToolhelp32Snapshot");
6283 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6285 return INVALID_HANDLE_VALUE
;
6287 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6291 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6293 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6295 if (g_b_init_process32_first
== 0)
6297 g_b_init_process32_first
= 1;
6298 s_pfn_Process32_First
= (Process32First_Proc
)
6299 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6302 if (s_pfn_Process32_First
== NULL
)
6306 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6310 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6312 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6314 if (g_b_init_process32_next
== 0)
6316 g_b_init_process32_next
= 1;
6317 s_pfn_Process32_Next
= (Process32Next_Proc
)
6318 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6321 if (s_pfn_Process32_Next
== NULL
)
6325 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6329 open_thread_token (HANDLE ThreadHandle
,
6330 DWORD DesiredAccess
,
6332 PHANDLE TokenHandle
)
6334 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6335 HMODULE hm_advapi32
= NULL
;
6336 if (is_windows_9x () == TRUE
)
6338 SetLastError (ERROR_NOT_SUPPORTED
);
6341 if (g_b_init_open_thread_token
== 0)
6343 g_b_init_open_thread_token
= 1;
6344 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6345 s_pfn_Open_Thread_Token
=
6346 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6348 if (s_pfn_Open_Thread_Token
== NULL
)
6350 SetLastError (ERROR_NOT_SUPPORTED
);
6354 s_pfn_Open_Thread_Token (
6363 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6365 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6366 HMODULE hm_advapi32
= NULL
;
6367 if (is_windows_9x () == TRUE
)
6371 if (g_b_init_impersonate_self
== 0)
6373 g_b_init_impersonate_self
= 1;
6374 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6375 s_pfn_Impersonate_Self
=
6376 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6378 if (s_pfn_Impersonate_Self
== NULL
)
6382 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6386 revert_to_self (void)
6388 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6389 HMODULE hm_advapi32
= NULL
;
6390 if (is_windows_9x () == TRUE
)
6394 if (g_b_init_revert_to_self
== 0)
6396 g_b_init_revert_to_self
= 1;
6397 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6398 s_pfn_Revert_To_Self
=
6399 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6401 if (s_pfn_Revert_To_Self
== NULL
)
6405 return s_pfn_Revert_To_Self ();
6409 get_process_memory_info (HANDLE h_proc
,
6410 PPROCESS_MEMORY_COUNTERS mem_counters
,
6413 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6414 HMODULE hm_psapi
= NULL
;
6415 if (is_windows_9x () == TRUE
)
6419 if (g_b_init_get_process_memory_info
== 0)
6421 g_b_init_get_process_memory_info
= 1;
6422 hm_psapi
= LoadLibrary ("Psapi.dll");
6424 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6425 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6427 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6431 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6435 get_process_working_set_size (HANDLE h_proc
,
6439 static GetProcessWorkingSetSize_Proc
6440 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6442 if (is_windows_9x () == TRUE
)
6446 if (g_b_init_get_process_working_set_size
== 0)
6448 g_b_init_get_process_working_set_size
= 1;
6449 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6450 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6451 "GetProcessWorkingSetSize");
6453 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6457 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6461 global_memory_status (MEMORYSTATUS
*buf
)
6463 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6465 if (is_windows_9x () == TRUE
)
6469 if (g_b_init_global_memory_status
== 0)
6471 g_b_init_global_memory_status
= 1;
6472 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6473 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6474 "GlobalMemoryStatus");
6476 if (s_pfn_Global_Memory_Status
== NULL
)
6480 return s_pfn_Global_Memory_Status (buf
);
6484 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6486 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6488 if (is_windows_9x () == TRUE
)
6492 if (g_b_init_global_memory_status_ex
== 0)
6494 g_b_init_global_memory_status_ex
= 1;
6495 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6496 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6497 "GlobalMemoryStatusEx");
6499 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6503 return s_pfn_Global_Memory_Status_Ex (buf
);
6507 list_system_processes (void)
6509 struct gcpro gcpro1
;
6510 Lisp_Object proclist
= Qnil
;
6513 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6515 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6517 PROCESSENTRY32 proc_entry
;
6523 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6524 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6525 res
= process32_next (h_snapshot
, &proc_entry
))
6527 proc_id
= proc_entry
.th32ProcessID
;
6528 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6531 CloseHandle (h_snapshot
);
6533 proclist
= Fnreverse (proclist
);
6540 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6542 TOKEN_PRIVILEGES priv
;
6543 DWORD priv_size
= sizeof (priv
);
6544 DWORD opriv_size
= sizeof (*old_priv
);
6545 HANDLE h_token
= NULL
;
6546 HANDLE h_thread
= GetCurrentThread ();
6550 res
= open_thread_token (h_thread
,
6551 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6553 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6555 if (impersonate_self (SecurityImpersonation
))
6556 res
= open_thread_token (h_thread
,
6557 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6562 priv
.PrivilegeCount
= 1;
6563 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6564 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6565 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6566 old_priv
, &opriv_size
)
6567 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6571 CloseHandle (h_token
);
6577 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6579 DWORD priv_size
= sizeof (*priv
);
6580 HANDLE h_token
= NULL
;
6583 if (open_thread_token (GetCurrentThread (),
6584 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6587 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6588 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6592 CloseHandle (h_token
);
6598 ltime (ULONGLONG time_100ns
)
6600 ULONGLONG time_sec
= time_100ns
/ 10000000;
6601 int subsec
= time_100ns
% 10000000;
6602 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6603 subsec
/ 10, subsec
% 10 * 100000);
6606 #define U64_TO_LISP_TIME(time) ltime (time)
6609 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6610 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6613 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6614 ULONGLONG tem1
, tem2
, tem3
, tem
;
6617 || !get_process_times_fn
6618 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6619 &ft_kernel
, &ft_user
))
6622 GetSystemTimeAsFileTime (&ft_current
);
6624 FILETIME_TO_U64 (tem1
, ft_kernel
);
6625 *stime
= U64_TO_LISP_TIME (tem1
);
6627 FILETIME_TO_U64 (tem2
, ft_user
);
6628 *utime
= U64_TO_LISP_TIME (tem2
);
6631 *ttime
= U64_TO_LISP_TIME (tem3
);
6633 FILETIME_TO_U64 (tem
, ft_creation
);
6634 /* Process no 4 (System) returns zero creation time. */
6637 *ctime
= U64_TO_LISP_TIME (tem
);
6641 FILETIME_TO_U64 (tem3
, ft_current
);
6642 tem
= (tem3
- utc_base
) - tem
;
6644 *etime
= U64_TO_LISP_TIME (tem
);
6648 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6659 system_process_attributes (Lisp_Object pid
)
6661 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6662 Lisp_Object attrs
= Qnil
;
6663 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6664 HANDLE h_snapshot
, h_proc
;
6667 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6668 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6669 DWORD glength
= sizeof (gname
);
6670 HANDLE token
= NULL
;
6671 SID_NAME_USE user_type
;
6672 unsigned char *buf
= NULL
;
6674 TOKEN_USER user_token
;
6675 TOKEN_PRIMARY_GROUP group_token
;
6678 PROCESS_MEMORY_COUNTERS mem
;
6679 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6680 SIZE_T minrss
, maxrss
;
6682 MEMORY_STATUS_EX memstex
;
6683 double totphys
= 0.0;
6684 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6686 BOOL result
= FALSE
;
6688 CHECK_NUMBER_OR_FLOAT (pid
);
6689 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6691 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6693 GCPRO3 (attrs
, decoded_cmd
, tem
);
6695 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6700 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6701 for (res
= process32_first (h_snapshot
, &pe
); res
;
6702 res
= process32_next (h_snapshot
, &pe
))
6704 if (proc_id
== pe
.th32ProcessID
)
6707 decoded_cmd
= build_string ("Idle");
6710 /* Decode the command name from locale-specific
6712 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6715 code_convert_string_norecord (cmd_str
,
6716 Vlocale_coding_system
, 0);
6718 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6719 attrs
= Fcons (Fcons (Qppid
,
6720 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6722 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6724 attrs
= Fcons (Fcons (Qthcount
,
6725 make_fixnum_or_float (pe
.cntThreads
)),
6732 CloseHandle (h_snapshot
);
6741 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6743 /* If we were denied a handle to the process, try again after
6744 enabling the SeDebugPrivilege in our process. */
6747 TOKEN_PRIVILEGES priv_current
;
6749 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6751 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6753 restore_privilege (&priv_current
);
6759 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6762 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6763 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6765 buf
= xmalloc (blen
);
6766 result
= get_token_information (token
, TokenUser
,
6767 (LPVOID
)buf
, blen
, &needed
);
6770 memcpy (&user_token
, buf
, sizeof (user_token
));
6771 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6773 euid
= get_rid (user_token
.User
.Sid
);
6774 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6779 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6782 strcpy (uname
, "unknown");
6786 ulength
= strlen (uname
);
6792 /* Determine a reasonable euid and gid values. */
6793 if (xstrcasecmp ("administrator", uname
) == 0)
6795 euid
= 500; /* well-known Administrator uid */
6796 egid
= 513; /* well-known None gid */
6800 /* Get group id and name. */
6801 result
= get_token_information (token
, TokenPrimaryGroup
,
6802 (LPVOID
)buf
, blen
, &needed
);
6803 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6805 buf
= xrealloc (buf
, blen
= needed
);
6806 result
= get_token_information (token
, TokenPrimaryGroup
,
6807 (LPVOID
)buf
, blen
, &needed
);
6811 memcpy (&group_token
, buf
, sizeof (group_token
));
6812 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6814 egid
= get_rid (group_token
.PrimaryGroup
);
6815 dlength
= sizeof (domain
);
6817 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6818 gname
, &glength
, NULL
, &dlength
,
6821 w32_add_to_cache (group_token
.PrimaryGroup
,
6825 strcpy (gname
, "None");
6829 glength
= strlen (gname
);
6837 if (!is_windows_9x ())
6839 /* We couldn't open the process token, presumably because of
6840 insufficient access rights. Assume this process is run
6842 strcpy (uname
, "SYSTEM");
6843 strcpy (gname
, "None");
6844 euid
= 18; /* SYSTEM */
6845 egid
= 513; /* None */
6846 glength
= strlen (gname
);
6847 ulength
= strlen (uname
);
6849 /* If we are running under Windows 9X, where security calls are
6850 not supported, we assume all processes are run by the current
6852 else if (GetUserName (uname
, &ulength
))
6854 if (xstrcasecmp ("administrator", uname
) == 0)
6859 strcpy (gname
, "None");
6860 glength
= strlen (gname
);
6861 ulength
= strlen (uname
);
6867 strcpy (uname
, "administrator");
6868 ulength
= strlen (uname
);
6869 strcpy (gname
, "None");
6870 glength
= strlen (gname
);
6873 CloseHandle (token
);
6876 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6877 tem
= make_unibyte_string (uname
, ulength
);
6878 attrs
= Fcons (Fcons (Quser
,
6879 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6881 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6882 tem
= make_unibyte_string (gname
, glength
);
6883 attrs
= Fcons (Fcons (Qgroup
,
6884 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6887 if (global_memory_status_ex (&memstex
))
6888 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6889 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6891 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6892 double, so we need to do this for it... */
6894 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6895 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6896 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6898 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6900 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6901 else if (global_memory_status (&memst
))
6902 totphys
= memst
.dwTotalPhys
/ 1024.0;
6905 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6908 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6910 attrs
= Fcons (Fcons (Qmajflt
,
6911 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6913 attrs
= Fcons (Fcons (Qvsize
,
6914 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6916 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6918 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6921 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6923 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6925 attrs
= Fcons (Fcons (Qmajflt
,
6926 make_fixnum_or_float (mem
.PageFaultCount
)),
6928 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6930 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6933 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6935 DWORD rss
= maxrss
/ 1024;
6937 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6939 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6942 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6944 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6945 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6946 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6947 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6948 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6949 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6952 /* FIXME: Retrieve command line by walking the PEB of the process. */
6955 CloseHandle (h_proc
);
6961 w32_memory_info (unsigned long long *totalram
, unsigned long long *freeram
,
6962 unsigned long long *totalswap
, unsigned long long *freeswap
)
6965 MEMORY_STATUS_EX memstex
;
6967 /* Use GlobalMemoryStatusEx if available, as it can report more than
6969 if (global_memory_status_ex (&memstex
))
6971 *totalram
= memstex
.ullTotalPhys
;
6972 *freeram
= memstex
.ullAvailPhys
;
6973 *totalswap
= memstex
.ullTotalPageFile
;
6974 *freeswap
= memstex
.ullAvailPageFile
;
6977 else if (global_memory_status (&memst
))
6979 *totalram
= memst
.dwTotalPhys
;
6980 *freeram
= memst
.dwAvailPhys
;
6981 *totalswap
= memst
.dwTotalPageFile
;
6982 *freeswap
= memst
.dwAvailPageFile
;
6990 /* Wrappers for winsock functions to map between our file descriptors
6991 and winsock's handles; also set h_errno for convenience.
6993 To allow Emacs to run on systems which don't have winsock support
6994 installed, we dynamically link to winsock on startup if present, and
6995 otherwise provide the minimum necessary functionality
6996 (eg. gethostname). */
6998 /* function pointers for relevant socket functions */
6999 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
7000 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
7001 int (PASCAL
*pfn_WSAGetLastError
) (void);
7002 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
7003 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
7004 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
7005 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
7006 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7007 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
7008 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
7009 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
7010 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
7011 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
7012 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
7013 int (PASCAL
*pfn_WSACleanup
) (void);
7015 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
7016 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
7017 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
7018 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
7019 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
7020 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
7021 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
7022 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
7023 const char * optval
, int optlen
);
7024 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
7025 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
7027 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
7028 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
7029 struct sockaddr
* from
, int * fromlen
);
7030 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
7031 const struct sockaddr
* to
, int tolen
);
7033 /* SetHandleInformation is only needed to make sockets non-inheritable. */
7034 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
7035 #ifndef HANDLE_FLAG_INHERIT
7036 #define HANDLE_FLAG_INHERIT 1
7040 static int winsock_inuse
;
7045 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
7047 release_listen_threads ();
7048 /* Not sure what would cause WSAENETDOWN, or even if it can happen
7049 after WSAStartup returns successfully, but it seems reasonable
7050 to allow unloading winsock anyway in that case. */
7051 if (pfn_WSACleanup () == 0 ||
7052 pfn_WSAGetLastError () == WSAENETDOWN
)
7054 if (FreeLibrary (winsock_lib
))
7063 init_winsock (int load_now
)
7065 WSADATA winsockData
;
7067 if (winsock_lib
!= NULL
)
7070 pfn_SetHandleInformation
7071 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
7072 "SetHandleInformation");
7074 winsock_lib
= LoadLibrary ("Ws2_32.dll");
7076 if (winsock_lib
!= NULL
)
7078 /* dynamically link to socket functions */
7080 #define LOAD_PROC(fn) \
7081 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
7084 LOAD_PROC (WSAStartup
);
7085 LOAD_PROC (WSASetLastError
);
7086 LOAD_PROC (WSAGetLastError
);
7087 LOAD_PROC (WSAEventSelect
);
7088 LOAD_PROC (WSACreateEvent
);
7089 LOAD_PROC (WSACloseEvent
);
7092 LOAD_PROC (connect
);
7093 LOAD_PROC (ioctlsocket
);
7096 LOAD_PROC (closesocket
);
7097 LOAD_PROC (shutdown
);
7100 LOAD_PROC (inet_addr
);
7101 LOAD_PROC (gethostname
);
7102 LOAD_PROC (gethostbyname
);
7103 LOAD_PROC (getservbyname
);
7104 LOAD_PROC (getpeername
);
7105 LOAD_PROC (WSACleanup
);
7106 LOAD_PROC (setsockopt
);
7108 LOAD_PROC (getsockname
);
7110 LOAD_PROC (recvfrom
);
7114 /* specify version 1.1 of winsock */
7115 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
7117 if (winsockData
.wVersion
!= 0x101)
7122 /* Report that winsock exists and is usable, but leave
7123 socket functions disabled. I am assuming that calling
7124 WSAStartup does not require any network interaction,
7125 and in particular does not cause or require a dial-up
7126 connection to be established. */
7129 FreeLibrary (winsock_lib
);
7137 FreeLibrary (winsock_lib
);
7147 /* Function to map winsock error codes to errno codes for those errno
7148 code defined in errno.h (errno values not defined by errno.h are
7149 already in nt/inc/sys/socket.h). */
7156 if (winsock_lib
== NULL
)
7159 wsa_err
= pfn_WSAGetLastError ();
7163 case WSAEACCES
: errno
= EACCES
; break;
7164 case WSAEBADF
: errno
= EBADF
; break;
7165 case WSAEFAULT
: errno
= EFAULT
; break;
7166 case WSAEINTR
: errno
= EINTR
; break;
7167 case WSAEINVAL
: errno
= EINVAL
; break;
7168 case WSAEMFILE
: errno
= EMFILE
; break;
7169 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7170 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7171 default: errno
= wsa_err
; break;
7179 if (winsock_lib
!= NULL
)
7180 pfn_WSASetLastError (0);
7183 /* Extend strerror to handle the winsock-specific error codes. */
7187 } _wsa_errlist
[] = {
7188 {WSAEINTR
, "Interrupted function call"},
7189 {WSAEBADF
, "Bad file descriptor"},
7190 {WSAEACCES
, "Permission denied"},
7191 {WSAEFAULT
, "Bad address"},
7192 {WSAEINVAL
, "Invalid argument"},
7193 {WSAEMFILE
, "Too many open files"},
7195 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7196 {WSAEINPROGRESS
, "Operation now in progress"},
7197 {WSAEALREADY
, "Operation already in progress"},
7198 {WSAENOTSOCK
, "Socket operation on non-socket"},
7199 {WSAEDESTADDRREQ
, "Destination address required"},
7200 {WSAEMSGSIZE
, "Message too long"},
7201 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7202 {WSAENOPROTOOPT
, "Bad protocol option"},
7203 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7204 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7205 {WSAEOPNOTSUPP
, "Operation not supported"},
7206 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7207 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7208 {WSAEADDRINUSE
, "Address already in use"},
7209 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7210 {WSAENETDOWN
, "Network is down"},
7211 {WSAENETUNREACH
, "Network is unreachable"},
7212 {WSAENETRESET
, "Network dropped connection on reset"},
7213 {WSAECONNABORTED
, "Software caused connection abort"},
7214 {WSAECONNRESET
, "Connection reset by peer"},
7215 {WSAENOBUFS
, "No buffer space available"},
7216 {WSAEISCONN
, "Socket is already connected"},
7217 {WSAENOTCONN
, "Socket is not connected"},
7218 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7219 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7220 {WSAETIMEDOUT
, "Connection timed out"},
7221 {WSAECONNREFUSED
, "Connection refused"},
7222 {WSAELOOP
, "Network loop"}, /* not sure */
7223 {WSAENAMETOOLONG
, "Name is too long"},
7224 {WSAEHOSTDOWN
, "Host is down"},
7225 {WSAEHOSTUNREACH
, "No route to host"},
7226 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7227 {WSAEPROCLIM
, "Too many processes"},
7228 {WSAEUSERS
, "Too many users"}, /* not sure */
7229 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7230 {WSAESTALE
, "Data is stale"}, /* not sure */
7231 {WSAEREMOTE
, "Remote error"}, /* not sure */
7233 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7234 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7235 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7236 {WSAEDISCON
, "Graceful shutdown in progress"},
7238 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7239 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7240 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7241 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7242 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7243 {WSASYSCALLFAILURE
, "System call failure"},
7244 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7245 {WSATYPE_NOT_FOUND
, "Class type not found"},
7246 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7247 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7248 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7251 {WSAHOST_NOT_FOUND
, "Host not found"},
7252 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7253 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7254 {WSANO_DATA
, "Valid name, no data record of requested type"},
7260 sys_strerror (int error_no
)
7263 static char unknown_msg
[40];
7265 if (error_no
>= 0 && error_no
< sys_nerr
)
7266 return sys_errlist
[error_no
];
7268 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7269 if (_wsa_errlist
[i
].errnum
== error_no
)
7270 return _wsa_errlist
[i
].msg
;
7272 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7276 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7277 but I believe the method of keeping the socket handle separate (and
7278 insuring it is not inheritable) is the correct one. */
7280 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7282 static int socket_to_fd (SOCKET s
);
7285 sys_socket (int af
, int type
, int protocol
)
7289 if (winsock_lib
== NULL
)
7292 return INVALID_SOCKET
;
7297 /* call the real socket function */
7298 s
= pfn_socket (af
, type
, protocol
);
7300 if (s
!= INVALID_SOCKET
)
7301 return socket_to_fd (s
);
7307 /* Convert a SOCKET to a file descriptor. */
7309 socket_to_fd (SOCKET s
)
7314 /* Although under NT 3.5 _open_osfhandle will accept a socket
7315 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7316 that does not work under NT 3.1. However, we can get the same
7317 effect by using a backdoor function to replace an existing
7318 descriptor handle with the one we want. */
7320 /* allocate a file descriptor (with appropriate flags) */
7321 fd
= _open ("NUL:", _O_RDWR
);
7324 /* Make a non-inheritable copy of the socket handle. Note
7325 that it is possible that sockets aren't actually kernel
7326 handles, which appears to be the case on Windows 9x when
7327 the MS Proxy winsock client is installed. */
7329 /* Apparently there is a bug in NT 3.51 with some service
7330 packs, which prevents using DuplicateHandle to make a
7331 socket handle non-inheritable (causes WSACleanup to
7332 hang). The work-around is to use SetHandleInformation
7333 instead if it is available and implemented. */
7334 if (pfn_SetHandleInformation
)
7336 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7340 HANDLE parent
= GetCurrentProcess ();
7341 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7343 if (DuplicateHandle (parent
,
7349 DUPLICATE_SAME_ACCESS
))
7351 /* It is possible that DuplicateHandle succeeds even
7352 though the socket wasn't really a kernel handle,
7353 because a real handle has the same value. So
7354 test whether the new handle really is a socket. */
7355 long nonblocking
= 0;
7356 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7358 pfn_closesocket (s
);
7363 CloseHandle (new_s
);
7368 eassert (fd
< MAXDESC
);
7369 fd_info
[fd
].hnd
= (HANDLE
) s
;
7371 /* set our own internal flags */
7372 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7378 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7380 /* attach child_process to fd_info */
7381 if (fd_info
[ fd
].cp
!= NULL
)
7383 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7387 fd_info
[ fd
].cp
= cp
;
7390 winsock_inuse
++; /* count open sockets */
7398 pfn_closesocket (s
);
7404 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7406 if (winsock_lib
== NULL
)
7409 return SOCKET_ERROR
;
7413 if (fd_info
[s
].flags
& FILE_SOCKET
)
7415 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7416 if (rc
== SOCKET_ERROR
)
7421 return SOCKET_ERROR
;
7425 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7427 if (winsock_lib
== NULL
)
7430 return SOCKET_ERROR
;
7434 if (fd_info
[s
].flags
& FILE_SOCKET
)
7436 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7437 if (rc
== SOCKET_ERROR
)
7442 return SOCKET_ERROR
;
7446 sys_htons (u_short hostshort
)
7448 return (winsock_lib
!= NULL
) ?
7449 pfn_htons (hostshort
) : hostshort
;
7453 sys_ntohs (u_short netshort
)
7455 return (winsock_lib
!= NULL
) ?
7456 pfn_ntohs (netshort
) : netshort
;
7460 sys_inet_addr (const char * cp
)
7462 return (winsock_lib
!= NULL
) ?
7463 pfn_inet_addr (cp
) : INADDR_NONE
;
7467 sys_gethostname (char * name
, int namelen
)
7469 if (winsock_lib
!= NULL
)
7474 retval
= pfn_gethostname (name
, namelen
);
7475 if (retval
== SOCKET_ERROR
)
7480 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7481 return !GetComputerName (name
, (DWORD
*)&namelen
);
7484 return SOCKET_ERROR
;
7488 sys_gethostbyname (const char * name
)
7490 struct hostent
* host
;
7491 int h_err
= h_errno
;
7493 if (winsock_lib
== NULL
)
7495 h_errno
= NO_RECOVERY
;
7501 host
= pfn_gethostbyname (name
);
7513 sys_getservbyname (const char * name
, const char * proto
)
7515 struct servent
* serv
;
7517 if (winsock_lib
== NULL
)
7524 serv
= pfn_getservbyname (name
, proto
);
7531 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7533 if (winsock_lib
== NULL
)
7536 return SOCKET_ERROR
;
7540 if (fd_info
[s
].flags
& FILE_SOCKET
)
7542 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7543 if (rc
== SOCKET_ERROR
)
7548 return SOCKET_ERROR
;
7552 sys_shutdown (int s
, int how
)
7554 if (winsock_lib
== NULL
)
7557 return SOCKET_ERROR
;
7561 if (fd_info
[s
].flags
& FILE_SOCKET
)
7563 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7564 if (rc
== SOCKET_ERROR
)
7569 return SOCKET_ERROR
;
7573 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7575 if (winsock_lib
== NULL
)
7578 return SOCKET_ERROR
;
7582 if (fd_info
[s
].flags
& FILE_SOCKET
)
7584 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7585 (const char *)optval
, optlen
);
7586 if (rc
== SOCKET_ERROR
)
7591 return SOCKET_ERROR
;
7595 sys_listen (int s
, int backlog
)
7597 if (winsock_lib
== NULL
)
7600 return SOCKET_ERROR
;
7604 if (fd_info
[s
].flags
& FILE_SOCKET
)
7606 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7607 if (rc
== SOCKET_ERROR
)
7610 fd_info
[s
].flags
|= FILE_LISTEN
;
7614 return SOCKET_ERROR
;
7618 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7620 if (winsock_lib
== NULL
)
7623 return SOCKET_ERROR
;
7627 if (fd_info
[s
].flags
& FILE_SOCKET
)
7629 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7630 if (rc
== SOCKET_ERROR
)
7635 return SOCKET_ERROR
;
7639 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7641 if (winsock_lib
== NULL
)
7648 if (fd_info
[s
].flags
& FILE_LISTEN
)
7650 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7652 if (t
== INVALID_SOCKET
)
7655 fd
= socket_to_fd (t
);
7659 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7660 ResetEvent (fd_info
[s
].cp
->char_avail
);
7669 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7670 struct sockaddr
* from
, int * fromlen
)
7672 if (winsock_lib
== NULL
)
7675 return SOCKET_ERROR
;
7679 if (fd_info
[s
].flags
& FILE_SOCKET
)
7681 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7682 if (rc
== SOCKET_ERROR
)
7687 return SOCKET_ERROR
;
7691 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7692 const struct sockaddr
* to
, int tolen
)
7694 if (winsock_lib
== NULL
)
7697 return SOCKET_ERROR
;
7701 if (fd_info
[s
].flags
& FILE_SOCKET
)
7703 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7704 if (rc
== SOCKET_ERROR
)
7709 return SOCKET_ERROR
;
7712 /* Windows does not have an fcntl function. Provide an implementation
7713 good enough for Emacs. */
7715 fcntl (int s
, int cmd
, int options
)
7717 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7718 invoked in a context where fd1 is closed and all descriptors less
7719 than fd1 are open, so sys_dup is an adequate implementation. */
7720 if (cmd
== F_DUPFD_CLOEXEC
)
7723 if (winsock_lib
== NULL
)
7730 if (fd_info
[s
].flags
& FILE_SOCKET
)
7732 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7734 unsigned long nblock
= 1;
7735 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7736 if (rc
== SOCKET_ERROR
)
7738 /* Keep track of the fact that we set this to non-blocking. */
7739 fd_info
[s
].flags
|= FILE_NDELAY
;
7745 return SOCKET_ERROR
;
7749 return SOCKET_ERROR
;
7753 /* Shadow main io functions: we need to handle pipes and sockets more
7754 intelligently, and implement non-blocking mode as well. */
7767 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7769 child_process
* cp
= fd_info
[fd
].cp
;
7771 fd_info
[fd
].cp
= NULL
;
7773 if (CHILD_ACTIVE (cp
))
7775 /* if last descriptor to active child_process then cleanup */
7777 for (i
= 0; i
< MAXDESC
; i
++)
7781 if (fd_info
[i
].cp
== cp
)
7786 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7788 if (winsock_lib
== NULL
) emacs_abort ();
7790 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7791 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7793 winsock_inuse
--; /* count open sockets */
7795 /* If the process handle is NULL, it's either a socket
7796 or serial connection, or a subprocess that was
7797 already reaped by reap_subprocess, but whose
7798 resources were not yet freed, because its output was
7799 not fully read yet by the time it was reaped. (This
7800 usually happens with async subprocesses whose output
7801 is being read by Emacs.) Otherwise, this process was
7802 not reaped yet, so we set its FD to a negative value
7803 to make sure sys_select will eventually get to
7804 calling the SIGCHLD handler for it, which will then
7805 invoke waitpid and reap_subprocess. */
7806 if (cp
->procinfo
.hProcess
== NULL
)
7814 if (fd
>= 0 && fd
< MAXDESC
)
7815 fd_info
[fd
].flags
= 0;
7817 /* Note that sockets do not need special treatment here (at least on
7818 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7819 closesocket is equivalent to CloseHandle, which is to be expected
7820 because socket handles are fully fledged kernel handles. */
7832 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7834 /* duplicate our internal info as well */
7835 fd_info
[new_fd
] = fd_info
[fd
];
7841 sys_dup2 (int src
, int dst
)
7845 if (dst
< 0 || dst
>= MAXDESC
)
7851 /* make sure we close the destination first if it's a pipe or socket */
7852 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7855 rc
= _dup2 (src
, dst
);
7858 /* duplicate our internal info as well */
7859 fd_info
[dst
] = fd_info
[src
];
7865 pipe2 (int * phandles
, int pipe2_flags
)
7870 eassert (pipe2_flags
== (O_BINARY
| O_CLOEXEC
));
7872 /* make pipe handles non-inheritable; when we spawn a child, we
7873 replace the relevant handle with an inheritable one. Also put
7874 pipes into binary mode; we will do text mode translation ourselves
7876 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7880 /* Protect against overflow, since Windows can open more handles than
7881 our fd_info array has room for. */
7882 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7884 _close (phandles
[0]);
7885 _close (phandles
[1]);
7891 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7892 fd_info
[phandles
[0]].flags
= flags
;
7894 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7895 fd_info
[phandles
[1]].flags
= flags
;
7902 /* Function to do blocking read of one byte, needed to implement
7903 select. It is only allowed on communication ports, sockets, or
7906 _sys_read_ahead (int fd
)
7911 if (fd
< 0 || fd
>= MAXDESC
)
7912 return STATUS_READ_ERROR
;
7914 cp
= fd_info
[fd
].cp
;
7916 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7917 return STATUS_READ_ERROR
;
7919 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7920 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7922 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7926 cp
->status
= STATUS_READ_IN_PROGRESS
;
7928 if (fd_info
[fd
].flags
& FILE_PIPE
)
7930 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7932 /* Give subprocess time to buffer some more output for us before
7933 reporting that input is available; we need this because Windows 95
7934 connects DOS programs to pipes by making the pipe appear to be
7935 the normal console stdout - as a result most DOS programs will
7936 write to stdout without buffering, ie. one character at a
7937 time. Even some W32 programs do this - "dir" in a command
7938 shell on NT is very slow if we don't do this. */
7941 int wait
= w32_pipe_read_delay
;
7947 /* Yield remainder of our time slice, effectively giving a
7948 temporary priority boost to the child process. */
7952 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7954 HANDLE hnd
= fd_info
[fd
].hnd
;
7955 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7958 /* Configure timeouts for blocking read. */
7959 if (!GetCommTimeouts (hnd
, &ct
))
7961 cp
->status
= STATUS_READ_ERROR
;
7962 return STATUS_READ_ERROR
;
7964 ct
.ReadIntervalTimeout
= 0;
7965 ct
.ReadTotalTimeoutMultiplier
= 0;
7966 ct
.ReadTotalTimeoutConstant
= 0;
7967 if (!SetCommTimeouts (hnd
, &ct
))
7969 cp
->status
= STATUS_READ_ERROR
;
7970 return STATUS_READ_ERROR
;
7973 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7975 if (GetLastError () != ERROR_IO_PENDING
)
7977 cp
->status
= STATUS_READ_ERROR
;
7978 return STATUS_READ_ERROR
;
7980 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7982 cp
->status
= STATUS_READ_ERROR
;
7983 return STATUS_READ_ERROR
;
7987 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7989 unsigned long nblock
= 0;
7990 /* We always want this to block, so temporarily disable NDELAY. */
7991 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7992 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7994 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7996 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7999 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8003 if (rc
== sizeof (char))
8004 cp
->status
= STATUS_READ_SUCCEEDED
;
8006 cp
->status
= STATUS_READ_FAILED
;
8012 _sys_wait_accept (int fd
)
8018 if (fd
< 0 || fd
>= MAXDESC
)
8019 return STATUS_READ_ERROR
;
8021 cp
= fd_info
[fd
].cp
;
8023 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
8024 return STATUS_READ_ERROR
;
8026 cp
->status
= STATUS_READ_FAILED
;
8028 hEv
= pfn_WSACreateEvent ();
8029 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
8030 if (rc
!= SOCKET_ERROR
)
8033 rc
= WaitForSingleObject (hEv
, 500);
8035 } while (rc
== WAIT_TIMEOUT
8036 && cp
->status
!= STATUS_READ_ERROR
8038 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
8039 if (rc
== WAIT_OBJECT_0
)
8040 cp
->status
= STATUS_READ_SUCCEEDED
;
8042 pfn_WSACloseEvent (hEv
);
8048 sys_read (int fd
, char * buffer
, unsigned int count
)
8053 char * orig_buffer
= buffer
;
8061 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8063 child_process
*cp
= fd_info
[fd
].cp
;
8065 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
8073 /* re-read CR carried over from last read */
8074 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
8076 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
8080 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
8083 /* presence of a child_process structure means we are operating in
8084 non-blocking mode - otherwise we just call _read directly.
8085 Note that the child_process structure might be missing because
8086 reap_subprocess has been called; in this case the pipe is
8087 already broken, so calling _read on it is okay. */
8090 int current_status
= cp
->status
;
8092 switch (current_status
)
8094 case STATUS_READ_FAILED
:
8095 case STATUS_READ_ERROR
:
8096 /* report normal EOF if nothing in buffer */
8098 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8101 case STATUS_READ_READY
:
8102 case STATUS_READ_IN_PROGRESS
:
8103 DebPrint (("sys_read called when read is in progress\n"));
8104 errno
= EWOULDBLOCK
;
8107 case STATUS_READ_SUCCEEDED
:
8108 /* consume read-ahead char */
8109 *buffer
++ = cp
->chr
;
8112 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8113 ResetEvent (cp
->char_avail
);
8115 case STATUS_READ_ACKNOWLEDGED
:
8119 DebPrint (("sys_read: bad status %d\n", current_status
));
8124 if (fd_info
[fd
].flags
& FILE_PIPE
)
8126 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
8127 to_read
= min (waiting
, (DWORD
) count
);
8130 nchars
+= _read (fd
, buffer
, to_read
);
8132 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
8134 HANDLE hnd
= fd_info
[fd
].hnd
;
8135 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
8141 /* Configure timeouts for non-blocking read. */
8142 if (!GetCommTimeouts (hnd
, &ct
))
8147 ct
.ReadIntervalTimeout
= MAXDWORD
;
8148 ct
.ReadTotalTimeoutMultiplier
= 0;
8149 ct
.ReadTotalTimeoutConstant
= 0;
8150 if (!SetCommTimeouts (hnd
, &ct
))
8156 if (!ResetEvent (ovl
->hEvent
))
8161 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8163 if (GetLastError () != ERROR_IO_PENDING
)
8168 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8177 else /* FILE_SOCKET */
8179 if (winsock_lib
== NULL
) emacs_abort ();
8181 /* do the equivalent of a non-blocking read */
8182 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8183 if (waiting
== 0 && nchars
== 0)
8185 errno
= EWOULDBLOCK
;
8191 /* always use binary mode for sockets */
8192 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8193 if (res
== SOCKET_ERROR
)
8195 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8196 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8206 int nread
= _read (fd
, buffer
, count
);
8209 else if (nchars
== 0)
8214 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8215 /* Perform text mode translation if required. */
8216 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8218 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8219 /* If buffer contains only CR, return that. To be absolutely
8220 sure we should attempt to read the next char, but in
8221 practice a CR to be followed by LF would not appear by
8222 itself in the buffer. */
8223 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8225 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8231 nchars
= _read (fd
, buffer
, count
);
8236 /* From w32xfns.c */
8237 extern HANDLE interrupt_handle
;
8239 /* For now, don't bother with a non-blocking mode */
8241 sys_write (int fd
, const void * buffer
, unsigned int count
)
8251 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8253 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8259 /* Perform text mode translation if required. */
8260 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8262 char * tmpbuf
= alloca (count
* 2);
8263 unsigned char * src
= (void *)buffer
;
8264 unsigned char * dst
= tmpbuf
;
8269 unsigned char *next
;
8270 /* copy next line or remaining bytes */
8271 next
= _memccpy (dst
, src
, '\n', nbytes
);
8274 /* copied one line ending with '\n' */
8275 int copied
= next
- dst
;
8278 /* insert '\r' before '\n' */
8285 /* copied remaining partial line -> now finished */
8292 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8294 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8295 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8296 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8299 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8301 if (GetLastError () != ERROR_IO_PENDING
)
8306 if (detect_input_pending ())
8307 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8310 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8311 if (active
== WAIT_OBJECT_0
)
8312 { /* User pressed C-g, cancel write, then leave. Don't bother
8313 cleaning up as we may only get stuck in buggy drivers. */
8314 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8319 if (active
== WAIT_OBJECT_0
+ 1
8320 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8327 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8329 unsigned long nblock
= 0;
8330 if (winsock_lib
== NULL
) emacs_abort ();
8332 /* TODO: implement select() properly so non-blocking I/O works. */
8333 /* For now, make sure the write blocks. */
8334 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8335 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8337 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8339 /* Set the socket back to non-blocking if it was before,
8340 for other operations that support it. */
8341 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8344 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8347 if (nchars
== SOCKET_ERROR
)
8349 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8350 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8356 /* Some networked filesystems don't like too large writes, so
8357 break them into smaller chunks. See the Comments section of
8358 the MSDN documentation of WriteFile for details behind the
8359 choice of the value of CHUNK below. See also the thread
8360 http://thread.gmane.org/gmane.comp.version-control.git/145294
8361 in the git mailing list. */
8362 const unsigned char *p
= buffer
;
8363 const unsigned chunk
= 30 * 1024 * 1024;
8368 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8369 int n
= _write (fd
, p
, this_chunk
);
8377 else if (n
< this_chunk
)
8388 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8390 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8392 /* Return information about network interface IFNAME, or about all
8393 interfaces (if IFNAME is nil). */
8395 network_interface_get_info (Lisp_Object ifname
)
8397 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8398 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8399 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8400 Lisp_Object res
= Qnil
;
8402 if (retval
== ERROR_BUFFER_OVERFLOW
)
8404 ainfo
= xrealloc (ainfo
, ainfo_len
);
8405 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8408 if (retval
== ERROR_SUCCESS
)
8410 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8411 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8413 struct sockaddr_in sa
;
8415 /* For the below, we need some winsock functions, so make sure
8416 the winsock DLL is loaded. If we cannot successfully load
8417 it, they will have no use of the information we provide,
8419 if (!winsock_lib
&& !init_winsock (1))
8422 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8424 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8426 /* Present Unix-compatible interface names, instead of the
8427 Windows names, which are really GUIDs not readable by
8429 static const char *ifmt
[] = {
8430 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8445 switch (adapter
->Type
)
8447 case MIB_IF_TYPE_ETHERNET
:
8448 /* Windows before Vista reports wireless adapters as
8449 Ethernet. Work around by looking at the Description
8451 if (strstr (adapter
->Description
, "Wireless "))
8454 if_num
= wlan_count
++;
8458 ifmt_idx
= ETHERNET
;
8459 if_num
= eth_count
++;
8462 case MIB_IF_TYPE_TOKENRING
:
8463 ifmt_idx
= TOKENRING
;
8464 if_num
= tr_count
++;
8466 case MIB_IF_TYPE_FDDI
:
8468 if_num
= fddi_count
++;
8470 case MIB_IF_TYPE_PPP
:
8472 if_num
= ppp_count
++;
8474 case MIB_IF_TYPE_SLIP
:
8476 if_num
= sl_count
++;
8478 case IF_TYPE_IEEE80211
:
8480 if_num
= wlan_count
++;
8482 case MIB_IF_TYPE_LOOPBACK
:
8485 ifmt_idx
= LOOPBACK
;
8486 if_num
= lo_count
++;
8492 ifmt_idx
= OTHER_IF
;
8493 if_num
= ifx_count
++;
8496 if (ifmt_idx
== NONE
)
8498 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8500 sa
.sin_family
= AF_INET
;
8501 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8502 if (ip_addr
== INADDR_NONE
)
8504 /* Bogus address, skip this interface. */
8507 sa
.sin_addr
.s_addr
= ip_addr
;
8510 res
= Fcons (Fcons (build_string (namebuf
),
8511 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8512 sizeof (struct sockaddr
))),
8514 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8516 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8517 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8518 Lisp_Object flags
= Qnil
;
8522 /* Flags. We guess most of them by type, since the
8523 Windows flags are different and hard to get by. */
8524 flags
= Fcons (intern ("up"), flags
);
8525 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8527 flags
= Fcons (intern ("broadcast"), flags
);
8528 flags
= Fcons (intern ("multicast"), flags
);
8530 flags
= Fcons (intern ("running"), flags
);
8531 if (ifmt_idx
== PPP
)
8533 flags
= Fcons (intern ("pointopoint"), flags
);
8534 flags
= Fcons (intern ("noarp"), flags
);
8536 if (adapter
->HaveWins
)
8537 flags
= Fcons (intern ("WINS"), flags
);
8538 if (adapter
->DhcpEnabled
)
8539 flags
= Fcons (intern ("dynamic"), flags
);
8541 res
= Fcons (flags
, res
);
8543 /* Hardware address and its family. */
8544 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8545 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8546 /* Windows does not support AF_LINK or AF_PACKET family
8547 of addresses. Use an arbitrary family number that is
8548 identical to what GNU/Linux returns. */
8549 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8552 sa
.sin_family
= AF_INET
;
8553 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8554 if (net_mask
!= INADDR_NONE
)
8556 sa
.sin_addr
.s_addr
= net_mask
;
8558 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8559 sizeof (struct sockaddr
)),
8563 res
= Fcons (Qnil
, res
);
8565 sa
.sin_family
= AF_INET
;
8566 if (ip_addr
!= INADDR_NONE
)
8568 /* Broadcast address is only reported by
8569 GetAdaptersAddresses, which is of limited
8570 availability. Generate it on our own. */
8571 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8573 sa
.sin_addr
.s_addr
= bcast_addr
;
8575 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8576 sizeof (struct sockaddr
)),
8580 sa
.sin_addr
.s_addr
= ip_addr
;
8582 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8583 sizeof (struct sockaddr
)),
8587 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8590 /* GetAdaptersInfo is documented to not report loopback
8591 interfaces, so we generate one out of thin air. */
8594 sa
.sin_family
= AF_INET
;
8598 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8599 res
= Fcons (Fcons (build_string ("lo"),
8600 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8601 sizeof (struct sockaddr
))),
8604 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8606 res
= Fcons (Fcons (intern ("running"),
8607 Fcons (intern ("loopback"),
8608 Fcons (intern ("up"), Qnil
))), Qnil
);
8609 /* 772 is what 3 different GNU/Linux systems report for
8610 the loopback interface. */
8611 res
= Fcons (Fcons (make_number (772),
8612 Fmake_vector (make_number (6),
8615 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8616 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8617 sizeof (struct sockaddr
)),
8619 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8620 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8621 sizeof (struct sockaddr
)),
8623 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8624 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8625 sizeof (struct sockaddr
)),
8638 network_interface_list (void)
8640 return network_interface_get_info (Qnil
);
8644 network_interface_info (Lisp_Object ifname
)
8646 CHECK_STRING (ifname
);
8647 return network_interface_get_info (ifname
);
8651 /* The Windows CRT functions are "optimized for speed", so they don't
8652 check for timezone and DST changes if they were last called less
8653 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8654 all Emacs features that repeatedly call time functions (e.g.,
8655 display-time) are in real danger of missing timezone and DST
8656 changes. Calling tzset before each localtime call fixes that. */
8658 sys_localtime (const time_t *t
)
8661 return localtime (t
);
8666 /* Try loading LIBRARY_ID from the file(s) specified in
8667 Vdynamic_library_alist. If the library is loaded successfully,
8668 return the handle of the DLL, and record the filename in the
8669 property :loaded-from of LIBRARY_ID. If the library could not be
8670 found, or when it was already loaded (because the handle is not
8671 recorded anywhere, and so is lost after use), return NULL.
8673 We could also save the handle in :loaded-from, but currently
8674 there's no use case for it. */
8676 w32_delayed_load (Lisp_Object library_id
)
8678 HMODULE dll_handle
= NULL
;
8680 CHECK_SYMBOL (library_id
);
8682 if (CONSP (Vdynamic_library_alist
)
8683 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8685 Lisp_Object found
= Qnil
;
8686 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8689 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8691 Lisp_Object dll
= XCAR (dlls
);
8692 char name
[MAX_UTF8_PATH
];
8696 dll
= ENCODE_FILE (dll
);
8697 if (w32_unicode_filenames
)
8699 wchar_t name_w
[MAX_PATH
];
8701 filename_to_utf16 (SSDATA (dll
), name_w
);
8702 dll_handle
= LoadLibraryW (name_w
);
8705 res
= GetModuleFileNameW (dll_handle
, name_w
,
8708 filename_from_utf16 (name_w
, name
);
8713 char name_a
[MAX_PATH
];
8715 filename_to_ansi (SSDATA (dll
), name_a
);
8716 dll_handle
= LoadLibraryA (name_a
);
8719 res
= GetModuleFileNameA (dll_handle
, name_a
,
8722 filename_from_ansi (name_a
, name
);
8727 ptrdiff_t len
= strlen (name
);
8730 /* Possibly truncated */
8731 ? make_specified_string (name
, -1, len
, 1)
8733 /* This prevents thread start and end notifications
8734 from being sent to the DLL, for every thread we
8735 start. We don't need those notifications because
8736 threads we create never use any of these DLLs, only
8737 the main thread uses them. This is supposed to
8738 speed up thread creation. */
8739 DisableThreadLibraryCalls (dll_handle
);
8744 Fput (library_id
, QCloaded_from
, found
);
8752 check_windows_init_file (void)
8754 /* A common indication that Emacs is not installed properly is when
8755 it cannot find the Windows installation file. If this file does
8756 not exist in the expected place, tell the user. */
8758 if (!noninteractive
&& !inhibit_window_system
8759 /* Vload_path is not yet initialized when we are loading
8761 && NILP (Vpurify_flag
))
8763 Lisp_Object init_file
;
8766 /* Implementation note: this function runs early during Emacs
8767 startup, before startup.el is run. So Vload_path is still in
8768 its initial unibyte form, but it holds UTF-8 encoded file
8769 names, since init_callproc was already called. So we do not
8770 need to ENCODE_FILE here, but we do need to convert the file
8771 names from UTF-8 to ANSI. */
8772 init_file
= build_string ("term/w32-win");
8773 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
8776 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8777 char *init_file_name
= SDATA (init_file
);
8778 char *load_path
= SDATA (load_path_print
);
8779 char *buffer
= alloca (1024
8780 + strlen (init_file_name
)
8781 + strlen (load_path
));
8786 "The Emacs Windows initialization file \"%s.el\" "
8787 "could not be found in your Emacs installation. "
8788 "Emacs checked the following directories for this file:\n"
8790 "When Emacs cannot find this file, it usually means that it "
8791 "was not installed properly, or its distribution file was "
8792 "not unpacked properly.\nSee the README.W32 file in the "
8793 "top-level Emacs directory for more information.",
8794 init_file_name
, load_path
);
8795 needed
= pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8799 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8801 pMultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8803 needed
= pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8804 NULL
, 0, NULL
, NULL
);
8807 char *msg_a
= alloca (needed
+ 1);
8809 pWideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8816 "Emacs Abort Dialog",
8817 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8818 /* Use the low-level system abort. */
8829 term_ntproc (int ignored
)
8835 /* shutdown the socket interface if necessary */
8842 init_ntproc (int dumping
)
8844 sigset_t initial_mask
= 0;
8846 /* Initialize the socket interface now if available and requested by
8847 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8848 delayed until open-network-stream is called (w32-has-winsock can
8849 also be used to dynamically load or reload winsock).
8851 Conveniently, init_environment is called before us, so
8852 PRELOAD_WINSOCK can be set in the registry. */
8854 /* Always initialize this correctly. */
8857 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8858 init_winsock (TRUE
);
8860 /* Initial preparation for subprocess support: replace our standard
8861 handles with non-inheritable versions. */
8864 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8865 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8866 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8868 parent
= GetCurrentProcess ();
8870 /* ignore errors when duplicating and closing; typically the
8871 handles will be invalid when running as a gui program. */
8872 DuplicateHandle (parent
,
8873 GetStdHandle (STD_INPUT_HANDLE
),
8878 DUPLICATE_SAME_ACCESS
);
8880 DuplicateHandle (parent
,
8881 GetStdHandle (STD_OUTPUT_HANDLE
),
8886 DUPLICATE_SAME_ACCESS
);
8888 DuplicateHandle (parent
,
8889 GetStdHandle (STD_ERROR_HANDLE
),
8894 DUPLICATE_SAME_ACCESS
);
8900 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8901 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8903 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8906 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8907 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8909 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8912 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8913 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8915 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8919 /* unfortunately, atexit depends on implementation of malloc */
8920 /* atexit (term_ntproc); */
8923 /* Make sure we start with all signals unblocked. */
8924 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8925 signal (SIGABRT
, term_ntproc
);
8929 /* determine which drives are fixed, for GetCachedVolumeInformation */
8931 /* GetDriveType must have trailing backslash. */
8932 char drive
[] = "A:\\";
8934 /* Loop over all possible drive letters */
8935 while (*drive
<= 'Z')
8937 /* Record if this drive letter refers to a fixed drive. */
8938 fixed_drives
[DRIVE_INDEX (*drive
)] =
8939 (GetDriveType (drive
) == DRIVE_FIXED
);
8944 /* Reset the volume info cache. */
8945 volume_cache
= NULL
;
8950 shutdown_handler ensures that buffers' autosave files are
8951 up to date when the user logs off, or the system shuts down.
8954 shutdown_handler (DWORD type
)
8956 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8957 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8958 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8959 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8961 /* Shut down cleanly, making sure autosave files are up to date. */
8962 shut_down_emacs (0, Qnil
);
8965 /* Allow other handlers to handle this signal. */
8969 /* On Windows 9X, load UNICOWS.DLL and return its handle, or die. On
8970 NT, return a handle to GDI32.DLL. */
8972 maybe_load_unicows_dll (void)
8974 if (os_subtype
== OS_9X
)
8976 HANDLE ret
= LoadLibrary ("Unicows.dll");
8979 /* These two functions are present on Windows 9X as stubs
8980 that always fail. We need the real implementations from
8981 UNICOWS.DLL, so we must call these functions through
8982 pointers, and assign the correct addresses to these
8983 pointers at program startup (see emacs.c, which calls
8984 this function early on). */
8985 pMultiByteToWideChar
= GetProcAddress (ret
, "MultiByteToWideChar");
8986 pWideCharToMultiByte
= GetProcAddress (ret
, "WideCharToMultiByte");
8993 button
= MessageBox (NULL
,
8994 "Emacs cannot load the UNICOWS.DLL library.\n"
8995 "This library is essential for using Emacs\n"
8996 "on this system. You need to install it.\n\n"
8997 "Emacs will exit when you click OK.",
8998 "Emacs cannot load UNICOWS.DLL",
8999 MB_ICONERROR
| MB_TASKMODAL
9000 | MB_SETFOREGROUND
| MB_OK
);
9011 /* On NT family of Windows, these two functions are always
9012 linked in, so we just assign their addresses to the 2
9013 pointers; no need for the LoadLibrary dance. */
9014 pMultiByteToWideChar
= MultiByteToWideChar
;
9015 pWideCharToMultiByte
= WideCharToMultiByte
;
9016 return LoadLibrary ("Gdi32.dll");
9021 globals_of_w32 is used to initialize those global variables that
9022 must always be initialized on startup even when the global variable
9023 initialized is non zero (see the function main in emacs.c).
9026 globals_of_w32 (void)
9028 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
9030 get_process_times_fn
= (GetProcessTimes_Proc
)
9031 GetProcAddress (kernel32
, "GetProcessTimes");
9033 DEFSYM (QCloaded_from
, ":loaded-from");
9035 g_b_init_is_windows_9x
= 0;
9036 g_b_init_open_process_token
= 0;
9037 g_b_init_get_token_information
= 0;
9038 g_b_init_lookup_account_sid
= 0;
9039 g_b_init_get_sid_sub_authority
= 0;
9040 g_b_init_get_sid_sub_authority_count
= 0;
9041 g_b_init_get_security_info
= 0;
9042 g_b_init_get_file_security_w
= 0;
9043 g_b_init_get_file_security_a
= 0;
9044 g_b_init_get_security_descriptor_owner
= 0;
9045 g_b_init_get_security_descriptor_group
= 0;
9046 g_b_init_is_valid_sid
= 0;
9047 g_b_init_create_toolhelp32_snapshot
= 0;
9048 g_b_init_process32_first
= 0;
9049 g_b_init_process32_next
= 0;
9050 g_b_init_open_thread_token
= 0;
9051 g_b_init_impersonate_self
= 0;
9052 g_b_init_revert_to_self
= 0;
9053 g_b_init_get_process_memory_info
= 0;
9054 g_b_init_get_process_working_set_size
= 0;
9055 g_b_init_global_memory_status
= 0;
9056 g_b_init_global_memory_status_ex
= 0;
9057 g_b_init_equal_sid
= 0;
9058 g_b_init_copy_sid
= 0;
9059 g_b_init_get_length_sid
= 0;
9060 g_b_init_get_native_system_info
= 0;
9061 g_b_init_get_system_times
= 0;
9062 g_b_init_create_symbolic_link_w
= 0;
9063 g_b_init_create_symbolic_link_a
= 0;
9064 g_b_init_get_security_descriptor_dacl
= 0;
9065 g_b_init_convert_sd_to_sddl
= 0;
9066 g_b_init_convert_sddl_to_sd
= 0;
9067 g_b_init_is_valid_security_descriptor
= 0;
9068 g_b_init_set_file_security_w
= 0;
9069 g_b_init_set_file_security_a
= 0;
9070 g_b_init_set_named_security_info_w
= 0;
9071 g_b_init_set_named_security_info_a
= 0;
9072 g_b_init_get_adapters_info
= 0;
9073 g_b_init_compare_string_w
= 0;
9074 num_of_processors
= 0;
9075 /* The following sets a handler for shutdown notifications for
9076 console apps. This actually applies to Emacs in both console and
9077 GUI modes, since we had to fool windows into thinking emacs is a
9078 console application to get console mode to work. */
9079 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
9081 /* "None" is the default group name on standalone workstations. */
9082 strcpy (dflt_group_name
, "None");
9084 /* Reset, in case it has some value inherited from dump time. */
9085 w32_stat_get_owner_group
= 0;
9087 /* If w32_unicode_filenames is non-zero, we will be using Unicode
9088 (a.k.a. "wide") APIs to invoke functions that accept file
9090 if (is_windows_9x ())
9091 w32_unicode_filenames
= 0;
9093 w32_unicode_filenames
= 1;
9096 /* For make-serial-process */
9098 serial_open (Lisp_Object port_obj
)
9100 char *port
= SSDATA (port_obj
);
9105 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
9106 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
9107 if (hnd
== INVALID_HANDLE_VALUE
)
9108 error ("Could not open %s", port
);
9109 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
9111 error ("Could not open %s", port
);
9115 error ("Could not create child process");
9117 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
9118 fd_info
[ fd
].hnd
= hnd
;
9119 fd_info
[ fd
].flags
|=
9120 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
9121 if (fd_info
[ fd
].cp
!= NULL
)
9123 error ("fd_info[fd = %d] is already in use", fd
);
9125 fd_info
[ fd
].cp
= cp
;
9126 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9127 if (cp
->ovl_read
.hEvent
== NULL
)
9128 error ("Could not create read event");
9129 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
9130 if (cp
->ovl_write
.hEvent
== NULL
)
9131 error ("Could not create write event");
9136 /* For serial-process-configure */
9138 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
9140 Lisp_Object childp2
= Qnil
;
9141 Lisp_Object tem
= Qnil
;
9145 char summary
[4] = "???"; /* This usually becomes "8N1". */
9147 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
9148 error ("Not a serial process");
9149 hnd
= fd_info
[ p
->outfd
].hnd
;
9151 childp2
= Fcopy_sequence (p
->childp
);
9153 /* Initialize timeouts for blocking read and blocking write. */
9154 if (!GetCommTimeouts (hnd
, &ct
))
9155 error ("GetCommTimeouts() failed");
9156 ct
.ReadIntervalTimeout
= 0;
9157 ct
.ReadTotalTimeoutMultiplier
= 0;
9158 ct
.ReadTotalTimeoutConstant
= 0;
9159 ct
.WriteTotalTimeoutMultiplier
= 0;
9160 ct
.WriteTotalTimeoutConstant
= 0;
9161 if (!SetCommTimeouts (hnd
, &ct
))
9162 error ("SetCommTimeouts() failed");
9163 /* Read port attributes and prepare default configuration. */
9164 memset (&dcb
, 0, sizeof (dcb
));
9165 dcb
.DCBlength
= sizeof (DCB
);
9166 if (!GetCommState (hnd
, &dcb
))
9167 error ("GetCommState() failed");
9170 dcb
.fAbortOnError
= FALSE
;
9171 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
9176 /* Configure speed. */
9177 if (!NILP (Fplist_member (contact
, QCspeed
)))
9178 tem
= Fplist_get (contact
, QCspeed
);
9180 tem
= Fplist_get (p
->childp
, QCspeed
);
9182 dcb
.BaudRate
= XINT (tem
);
9183 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
9185 /* Configure bytesize. */
9186 if (!NILP (Fplist_member (contact
, QCbytesize
)))
9187 tem
= Fplist_get (contact
, QCbytesize
);
9189 tem
= Fplist_get (p
->childp
, QCbytesize
);
9191 tem
= make_number (8);
9193 if (XINT (tem
) != 7 && XINT (tem
) != 8)
9194 error (":bytesize must be nil (8), 7, or 8");
9195 dcb
.ByteSize
= XINT (tem
);
9196 summary
[0] = XINT (tem
) + '0';
9197 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
9199 /* Configure parity. */
9200 if (!NILP (Fplist_member (contact
, QCparity
)))
9201 tem
= Fplist_get (contact
, QCparity
);
9203 tem
= Fplist_get (p
->childp
, QCparity
);
9204 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
9205 error (":parity must be nil (no parity), `even', or `odd'");
9206 dcb
.fParity
= FALSE
;
9207 dcb
.Parity
= NOPARITY
;
9208 dcb
.fErrorChar
= FALSE
;
9213 else if (EQ (tem
, Qeven
))
9217 dcb
.Parity
= EVENPARITY
;
9218 dcb
.fErrorChar
= TRUE
;
9220 else if (EQ (tem
, Qodd
))
9224 dcb
.Parity
= ODDPARITY
;
9225 dcb
.fErrorChar
= TRUE
;
9227 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9229 /* Configure stopbits. */
9230 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9231 tem
= Fplist_get (contact
, QCstopbits
);
9233 tem
= Fplist_get (p
->childp
, QCstopbits
);
9235 tem
= make_number (1);
9237 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9238 error (":stopbits must be nil (1 stopbit), 1, or 2");
9239 summary
[2] = XINT (tem
) + '0';
9240 if (XINT (tem
) == 1)
9241 dcb
.StopBits
= ONESTOPBIT
;
9242 else if (XINT (tem
) == 2)
9243 dcb
.StopBits
= TWOSTOPBITS
;
9244 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9246 /* Configure flowcontrol. */
9247 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9248 tem
= Fplist_get (contact
, QCflowcontrol
);
9250 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9251 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9252 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9253 dcb
.fOutxCtsFlow
= FALSE
;
9254 dcb
.fOutxDsrFlow
= FALSE
;
9255 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9256 dcb
.fDsrSensitivity
= FALSE
;
9257 dcb
.fTXContinueOnXoff
= FALSE
;
9260 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9261 dcb
.XonChar
= 17; /* Control-Q */
9262 dcb
.XoffChar
= 19; /* Control-S */
9265 /* Already configured. */
9267 else if (EQ (tem
, Qhw
))
9269 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9270 dcb
.fOutxCtsFlow
= TRUE
;
9272 else if (EQ (tem
, Qsw
))
9277 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9279 /* Activate configuration. */
9280 if (!SetCommState (hnd
, &dcb
))
9281 error ("SetCommState() failed");
9283 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9284 pset_childp (p
, childp2
);
9290 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9293 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9294 int fd
= process
->infd
;
9296 n
= sys_read (fd
, (char*)buf
, sz
);
9303 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9304 if (err
== EWOULDBLOCK
)
9307 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9313 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9315 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9316 int fd
= process
->outfd
;
9317 ssize_t n
= sys_write (fd
, buf
, sz
);
9319 /* 0 or more bytes written means everything went fine. */
9323 /* Negative bytes written means we got an error in errno.
9324 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9325 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9326 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9330 #endif /* HAVE_GNUTLS */