1 /* Utility and Unix shadow routines for GNU Emacs on the Microsoft Windows API.
3 Copyright (C) 1994-1995, 2000-2013 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 #if defined(__GNUC__) && !defined(_W64)
77 #define _ANONYMOUS_UNION
78 #define _ANONYMOUS_STRUCT
81 /* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
82 use a different name to avoid compilation problems. */
83 typedef struct _MEMORY_STATUS_EX
{
86 DWORDLONG ullTotalPhys
;
87 DWORDLONG ullAvailPhys
;
88 DWORDLONG ullTotalPageFile
;
89 DWORDLONG ullAvailPageFile
;
90 DWORDLONG ullTotalVirtual
;
91 DWORDLONG ullAvailVirtual
;
92 DWORDLONG ullAvailExtendedVirtual
;
93 } MEMORY_STATUS_EX
,*LPMEMORY_STATUS_EX
;
95 /* These are here so that GDB would know about these data types. This
96 allows to attach GDB to Emacs when a fatal exception is triggered
97 and Windows pops up the "application needs to be closed" dialog.
98 At that point, _gnu_exception_handler, the top-level exception
99 handler installed by the MinGW startup code, is somewhere on the
100 call-stack of the main thread, so going to that call frame and
101 looking at the argument to _gnu_exception_handler, which is a
102 PEXCEPTION_POINTERS pointer, can reveal the exception code
103 (excptr->ExceptionRecord->ExceptionCode) and the address where the
104 exception happened (excptr->ExceptionRecord->ExceptionAddress), as
105 well as some additional information specific to the exception. */
106 PEXCEPTION_POINTERS excptr
;
107 PEXCEPTION_RECORD excprec
;
113 #include <tlhelp32.h>
118 #if _WIN32_WINNT < 0x0500
119 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
120 /* This either is not in psapi.h or guarded by higher value of
121 _WIN32_WINNT than what we use. w32api supplied with MinGW 3.15
122 defines it in psapi.h */
123 typedef struct _PROCESS_MEMORY_COUNTERS_EX
{
125 DWORD PageFaultCount
;
126 SIZE_T PeakWorkingSetSize
;
127 SIZE_T WorkingSetSize
;
128 SIZE_T QuotaPeakPagedPoolUsage
;
129 SIZE_T QuotaPagedPoolUsage
;
130 SIZE_T QuotaPeakNonPagedPoolUsage
;
131 SIZE_T QuotaNonPagedPoolUsage
;
132 SIZE_T PagefileUsage
;
133 SIZE_T PeakPagefileUsage
;
135 } PROCESS_MEMORY_COUNTERS_EX
,*PPROCESS_MEMORY_COUNTERS_EX
;
139 #include <winioctl.h>
146 /* This is not in MinGW's sddl.h (but they are in MSVC headers), so we
147 define them by hand if not already defined. */
148 #ifndef SDDL_REVISION_1
149 #define SDDL_REVISION_1 1
150 #endif /* SDDL_REVISION_1 */
152 #if defined(_MSC_VER) || defined(_W64)
153 /* MSVC and MinGW64 don't provide the definition of
154 REPARSE_DATA_BUFFER and the associated macros, except on ntifs.h,
155 which cannot be included because it triggers conflicts with other
156 Windows API headers. So we define it here by hand. */
158 typedef struct _REPARSE_DATA_BUFFER
{
160 USHORT ReparseDataLength
;
164 USHORT SubstituteNameOffset
;
165 USHORT SubstituteNameLength
;
166 USHORT PrintNameOffset
;
167 USHORT PrintNameLength
;
170 } SymbolicLinkReparseBuffer
;
172 USHORT SubstituteNameOffset
;
173 USHORT SubstituteNameLength
;
174 USHORT PrintNameOffset
;
175 USHORT PrintNameLength
;
177 } MountPointReparseBuffer
;
180 } GenericReparseBuffer
;
182 } REPARSE_DATA_BUFFER
, *PREPARSE_DATA_BUFFER
;
184 #ifndef FILE_DEVICE_FILE_SYSTEM
185 #define FILE_DEVICE_FILE_SYSTEM 9
187 #ifndef METHOD_BUFFERED
188 #define METHOD_BUFFERED 0
190 #ifndef FILE_ANY_ACCESS
191 #define FILE_ANY_ACCESS 0x00000000
194 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
196 /* MinGW64 defines FSCTL_GET_REPARSE_POINT on winioctl.h. */
197 #ifndef FSCTL_GET_REPARSE_POINT
198 #define FSCTL_GET_REPARSE_POINT \
199 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
203 /* TCP connection support. */
204 #include <sys/socket.h>
223 #include <iphlpapi.h> /* should be after winsock2.h */
227 #include "w32common.h"
229 #include "w32select.h"
231 #include "dispextern.h" /* for xstrcasecmp */
232 #include "coding.h" /* for Vlocale_coding_system */
234 #include "careadlinkat.h"
235 #include "allocator.h"
237 /* For serial_configure and serial_open. */
240 typedef HRESULT (WINAPI
* ShGetFolderPath_fn
)
241 (IN HWND
, IN
int, IN HANDLE
, IN DWORD
, OUT
char *);
243 Lisp_Object QCloaded_from
;
245 void globals_of_w32 (void);
246 static DWORD
get_rid (PSID
);
247 static int is_symlink (const char *);
248 static char * chase_symlinks (const char *);
249 static int enable_privilege (LPCTSTR
, BOOL
, TOKEN_PRIVILEGES
*);
250 static int restore_privilege (TOKEN_PRIVILEGES
*);
251 static BOOL WINAPI
revert_to_self (void);
253 static int sys_access (const char *, int);
254 extern void *e_malloc (size_t);
255 extern int sys_select (int, SELECT_TYPE
*, SELECT_TYPE
*, SELECT_TYPE
*,
256 struct timespec
*, void *);
257 extern int sys_dup (int);
262 /* Initialization states.
264 WARNING: If you add any more such variables for additional APIs,
265 you MUST add initialization for them to globals_of_w32
266 below. This is because these variables might get set
267 to non-NULL values during dumping, but the dumped Emacs
268 cannot reuse those values, because it could be run on a
269 different version of the OS, where API addresses are
271 static BOOL g_b_init_is_windows_9x
;
272 static BOOL g_b_init_open_process_token
;
273 static BOOL g_b_init_get_token_information
;
274 static BOOL g_b_init_lookup_account_sid
;
275 static BOOL g_b_init_get_sid_sub_authority
;
276 static BOOL g_b_init_get_sid_sub_authority_count
;
277 static BOOL g_b_init_get_security_info
;
278 static BOOL g_b_init_get_file_security_w
;
279 static BOOL g_b_init_get_file_security_a
;
280 static BOOL g_b_init_get_security_descriptor_owner
;
281 static BOOL g_b_init_get_security_descriptor_group
;
282 static BOOL g_b_init_is_valid_sid
;
283 static BOOL g_b_init_create_toolhelp32_snapshot
;
284 static BOOL g_b_init_process32_first
;
285 static BOOL g_b_init_process32_next
;
286 static BOOL g_b_init_open_thread_token
;
287 static BOOL g_b_init_impersonate_self
;
288 static BOOL g_b_init_revert_to_self
;
289 static BOOL g_b_init_get_process_memory_info
;
290 static BOOL g_b_init_get_process_working_set_size
;
291 static BOOL g_b_init_global_memory_status
;
292 static BOOL g_b_init_global_memory_status_ex
;
293 static BOOL g_b_init_get_length_sid
;
294 static BOOL g_b_init_equal_sid
;
295 static BOOL g_b_init_copy_sid
;
296 static BOOL g_b_init_get_native_system_info
;
297 static BOOL g_b_init_get_system_times
;
298 static BOOL g_b_init_create_symbolic_link_w
;
299 static BOOL g_b_init_create_symbolic_link_a
;
300 static BOOL g_b_init_get_security_descriptor_dacl
;
301 static BOOL g_b_init_convert_sd_to_sddl
;
302 static BOOL g_b_init_convert_sddl_to_sd
;
303 static BOOL g_b_init_is_valid_security_descriptor
;
304 static BOOL g_b_init_set_file_security_w
;
305 static BOOL g_b_init_set_file_security_a
;
306 static BOOL g_b_init_get_adapters_info
;
309 BEGIN: Wrapper functions around OpenProcessToken
310 and other functions in advapi32.dll that are only
311 supported in Windows NT / 2k / XP
313 /* ** Function pointer typedefs ** */
314 typedef BOOL (WINAPI
* OpenProcessToken_Proc
) (
315 HANDLE ProcessHandle
,
317 PHANDLE TokenHandle
);
318 typedef BOOL (WINAPI
* GetTokenInformation_Proc
) (
320 TOKEN_INFORMATION_CLASS TokenInformationClass
,
321 LPVOID TokenInformation
,
322 DWORD TokenInformationLength
,
323 PDWORD ReturnLength
);
324 typedef BOOL (WINAPI
* GetProcessTimes_Proc
) (
325 HANDLE process_handle
,
326 LPFILETIME creation_time
,
327 LPFILETIME exit_time
,
328 LPFILETIME kernel_time
,
329 LPFILETIME user_time
);
331 GetProcessTimes_Proc get_process_times_fn
= NULL
;
334 const char * const LookupAccountSid_Name
= "LookupAccountSidW";
336 const char * const LookupAccountSid_Name
= "LookupAccountSidA";
338 typedef BOOL (WINAPI
* LookupAccountSid_Proc
) (
339 LPCTSTR lpSystemName
,
344 LPDWORD cbDomainName
,
345 PSID_NAME_USE peUse
);
346 typedef PDWORD (WINAPI
* GetSidSubAuthority_Proc
) (
349 typedef PUCHAR (WINAPI
* GetSidSubAuthorityCount_Proc
) (
351 typedef DWORD (WINAPI
* GetSecurityInfo_Proc
) (
353 SE_OBJECT_TYPE ObjectType
,
354 SECURITY_INFORMATION SecurityInfo
,
359 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
);
360 typedef BOOL (WINAPI
* GetFileSecurityW_Proc
) (
362 SECURITY_INFORMATION RequestedInformation
,
363 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
365 LPDWORD lpnLengthNeeded
);
366 typedef BOOL (WINAPI
* GetFileSecurityA_Proc
) (
368 SECURITY_INFORMATION RequestedInformation
,
369 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
371 LPDWORD lpnLengthNeeded
);
372 typedef BOOL (WINAPI
*SetFileSecurityW_Proc
) (
374 SECURITY_INFORMATION SecurityInformation
,
375 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
376 typedef BOOL (WINAPI
*SetFileSecurityA_Proc
) (
378 SECURITY_INFORMATION SecurityInformation
,
379 PSECURITY_DESCRIPTOR pSecurityDescriptor
);
380 typedef BOOL (WINAPI
* GetSecurityDescriptorOwner_Proc
) (
381 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
383 LPBOOL lpbOwnerDefaulted
);
384 typedef BOOL (WINAPI
* GetSecurityDescriptorGroup_Proc
) (
385 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
387 LPBOOL lpbGroupDefaulted
);
388 typedef BOOL (WINAPI
*GetSecurityDescriptorDacl_Proc
) (
389 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
390 LPBOOL lpbDaclPresent
,
392 LPBOOL lpbDaclDefaulted
);
393 typedef BOOL (WINAPI
* IsValidSid_Proc
) (
395 typedef HANDLE (WINAPI
* CreateToolhelp32Snapshot_Proc
) (
397 DWORD th32ProcessID
);
398 typedef BOOL (WINAPI
* Process32First_Proc
) (
400 LPPROCESSENTRY32 lppe
);
401 typedef BOOL (WINAPI
* Process32Next_Proc
) (
403 LPPROCESSENTRY32 lppe
);
404 typedef BOOL (WINAPI
* OpenThreadToken_Proc
) (
408 PHANDLE TokenHandle
);
409 typedef BOOL (WINAPI
* ImpersonateSelf_Proc
) (
410 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
411 typedef BOOL (WINAPI
* RevertToSelf_Proc
) (void);
412 typedef BOOL (WINAPI
* GetProcessMemoryInfo_Proc
) (
414 PPROCESS_MEMORY_COUNTERS ppsmemCounters
,
416 typedef BOOL (WINAPI
* GetProcessWorkingSetSize_Proc
) (
418 PSIZE_T lpMinimumWorkingSetSize
,
419 PSIZE_T lpMaximumWorkingSetSize
);
420 typedef BOOL (WINAPI
* GlobalMemoryStatus_Proc
) (
421 LPMEMORYSTATUS lpBuffer
);
422 typedef BOOL (WINAPI
* GlobalMemoryStatusEx_Proc
) (
423 LPMEMORY_STATUS_EX lpBuffer
);
424 typedef BOOL (WINAPI
* CopySid_Proc
) (
425 DWORD nDestinationSidLength
,
426 PSID pDestinationSid
,
428 typedef BOOL (WINAPI
* EqualSid_Proc
) (
431 typedef DWORD (WINAPI
* GetLengthSid_Proc
) (
433 typedef void (WINAPI
* GetNativeSystemInfo_Proc
) (
434 LPSYSTEM_INFO lpSystemInfo
);
435 typedef BOOL (WINAPI
* GetSystemTimes_Proc
) (
436 LPFILETIME lpIdleTime
,
437 LPFILETIME lpKernelTime
,
438 LPFILETIME lpUserTime
);
439 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkW_Proc
) (
440 LPCWSTR lpSymlinkFileName
,
441 LPCWSTR lpTargetFileName
,
443 typedef BOOLEAN (WINAPI
*CreateSymbolicLinkA_Proc
) (
444 LPCSTR lpSymlinkFileName
,
445 LPCSTR lpTargetFileName
,
447 typedef BOOL (WINAPI
*ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
) (
448 LPCTSTR StringSecurityDescriptor
,
449 DWORD StringSDRevision
,
450 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
451 PULONG SecurityDescriptorSize
);
452 typedef BOOL (WINAPI
*ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
) (
453 PSECURITY_DESCRIPTOR SecurityDescriptor
,
454 DWORD RequestedStringSDRevision
,
455 SECURITY_INFORMATION SecurityInformation
,
456 LPTSTR
*StringSecurityDescriptor
,
457 PULONG StringSecurityDescriptorLen
);
458 typedef BOOL (WINAPI
*IsValidSecurityDescriptor_Proc
) (PSECURITY_DESCRIPTOR
);
459 typedef DWORD (WINAPI
*GetAdaptersInfo_Proc
) (
460 PIP_ADAPTER_INFO pAdapterInfo
,
463 /* ** A utility function ** */
467 static BOOL s_b_ret
= 0;
468 OSVERSIONINFO os_ver
;
469 if (g_b_init_is_windows_9x
== 0)
471 g_b_init_is_windows_9x
= 1;
472 ZeroMemory (&os_ver
, sizeof (OSVERSIONINFO
));
473 os_ver
.dwOSVersionInfoSize
= sizeof (OSVERSIONINFO
);
474 if (GetVersionEx (&os_ver
))
476 s_b_ret
= (os_ver
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
);
482 static Lisp_Object
ltime (ULONGLONG
);
484 /* Get total user and system times for get-internal-run-time.
485 Returns a list of integers if the times are provided by the OS
486 (NT derivatives), otherwise it returns the result of current-time. */
488 w32_get_internal_run_time (void)
490 if (get_process_times_fn
)
492 FILETIME create
, exit
, kernel
, user
;
493 HANDLE proc
= GetCurrentProcess ();
494 if ((*get_process_times_fn
) (proc
, &create
, &exit
, &kernel
, &user
))
496 LARGE_INTEGER user_int
, kernel_int
, total
;
497 user_int
.LowPart
= user
.dwLowDateTime
;
498 user_int
.HighPart
= user
.dwHighDateTime
;
499 kernel_int
.LowPart
= kernel
.dwLowDateTime
;
500 kernel_int
.HighPart
= kernel
.dwHighDateTime
;
501 total
.QuadPart
= user_int
.QuadPart
+ kernel_int
.QuadPart
;
502 return ltime (total
.QuadPart
);
506 return Fcurrent_time ();
509 /* ** The wrapper functions ** */
512 open_process_token (HANDLE ProcessHandle
,
516 static OpenProcessToken_Proc s_pfn_Open_Process_Token
= NULL
;
517 HMODULE hm_advapi32
= NULL
;
518 if (is_windows_9x () == TRUE
)
522 if (g_b_init_open_process_token
== 0)
524 g_b_init_open_process_token
= 1;
525 hm_advapi32
= LoadLibrary ("Advapi32.dll");
526 s_pfn_Open_Process_Token
=
527 (OpenProcessToken_Proc
) GetProcAddress (hm_advapi32
, "OpenProcessToken");
529 if (s_pfn_Open_Process_Token
== NULL
)
534 s_pfn_Open_Process_Token (
542 get_token_information (HANDLE TokenHandle
,
543 TOKEN_INFORMATION_CLASS TokenInformationClass
,
544 LPVOID TokenInformation
,
545 DWORD TokenInformationLength
,
548 static GetTokenInformation_Proc s_pfn_Get_Token_Information
= NULL
;
549 HMODULE hm_advapi32
= NULL
;
550 if (is_windows_9x () == TRUE
)
554 if (g_b_init_get_token_information
== 0)
556 g_b_init_get_token_information
= 1;
557 hm_advapi32
= LoadLibrary ("Advapi32.dll");
558 s_pfn_Get_Token_Information
=
559 (GetTokenInformation_Proc
) GetProcAddress (hm_advapi32
, "GetTokenInformation");
561 if (s_pfn_Get_Token_Information
== NULL
)
566 s_pfn_Get_Token_Information (
568 TokenInformationClass
,
570 TokenInformationLength
,
576 lookup_account_sid (LPCTSTR lpSystemName
,
581 LPDWORD cbDomainName
,
584 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid
= NULL
;
585 HMODULE hm_advapi32
= NULL
;
586 if (is_windows_9x () == TRUE
)
590 if (g_b_init_lookup_account_sid
== 0)
592 g_b_init_lookup_account_sid
= 1;
593 hm_advapi32
= LoadLibrary ("Advapi32.dll");
594 s_pfn_Lookup_Account_Sid
=
595 (LookupAccountSid_Proc
) GetProcAddress (hm_advapi32
, LookupAccountSid_Name
);
597 if (s_pfn_Lookup_Account_Sid
== NULL
)
602 s_pfn_Lookup_Account_Sid (
614 get_sid_sub_authority (PSID pSid
, DWORD n
)
616 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority
= NULL
;
617 static DWORD zero
= 0U;
618 HMODULE hm_advapi32
= NULL
;
619 if (is_windows_9x () == TRUE
)
623 if (g_b_init_get_sid_sub_authority
== 0)
625 g_b_init_get_sid_sub_authority
= 1;
626 hm_advapi32
= LoadLibrary ("Advapi32.dll");
627 s_pfn_Get_Sid_Sub_Authority
=
628 (GetSidSubAuthority_Proc
) GetProcAddress (
629 hm_advapi32
, "GetSidSubAuthority");
631 if (s_pfn_Get_Sid_Sub_Authority
== NULL
)
635 return (s_pfn_Get_Sid_Sub_Authority (pSid
, n
));
639 get_sid_sub_authority_count (PSID pSid
)
641 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count
= NULL
;
642 static UCHAR zero
= 0U;
643 HMODULE hm_advapi32
= NULL
;
644 if (is_windows_9x () == TRUE
)
648 if (g_b_init_get_sid_sub_authority_count
== 0)
650 g_b_init_get_sid_sub_authority_count
= 1;
651 hm_advapi32
= LoadLibrary ("Advapi32.dll");
652 s_pfn_Get_Sid_Sub_Authority_Count
=
653 (GetSidSubAuthorityCount_Proc
) GetProcAddress (
654 hm_advapi32
, "GetSidSubAuthorityCount");
656 if (s_pfn_Get_Sid_Sub_Authority_Count
== NULL
)
660 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid
));
664 get_security_info (HANDLE handle
,
665 SE_OBJECT_TYPE ObjectType
,
666 SECURITY_INFORMATION SecurityInfo
,
671 PSECURITY_DESCRIPTOR
*ppSecurityDescriptor
)
673 static GetSecurityInfo_Proc s_pfn_Get_Security_Info
= NULL
;
674 HMODULE hm_advapi32
= NULL
;
675 if (is_windows_9x () == TRUE
)
679 if (g_b_init_get_security_info
== 0)
681 g_b_init_get_security_info
= 1;
682 hm_advapi32
= LoadLibrary ("Advapi32.dll");
683 s_pfn_Get_Security_Info
=
684 (GetSecurityInfo_Proc
) GetProcAddress (
685 hm_advapi32
, "GetSecurityInfo");
687 if (s_pfn_Get_Security_Info
== NULL
)
691 return (s_pfn_Get_Security_Info (handle
, ObjectType
, SecurityInfo
,
692 ppsidOwner
, ppsidGroup
, ppDacl
, ppSacl
,
693 ppSecurityDescriptor
));
697 get_file_security (const char *lpFileName
,
698 SECURITY_INFORMATION RequestedInformation
,
699 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
701 LPDWORD lpnLengthNeeded
)
703 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA
= NULL
;
704 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW
= NULL
;
705 HMODULE hm_advapi32
= NULL
;
706 if (is_windows_9x () == TRUE
)
711 if (w32_unicode_filenames
)
713 wchar_t filename_w
[MAX_PATH
];
715 if (g_b_init_get_file_security_w
== 0)
717 g_b_init_get_file_security_w
= 1;
718 hm_advapi32
= LoadLibrary ("Advapi32.dll");
719 s_pfn_Get_File_SecurityW
=
720 (GetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
723 if (s_pfn_Get_File_SecurityW
== NULL
)
728 filename_to_utf16 (lpFileName
, filename_w
);
729 return (s_pfn_Get_File_SecurityW (filename_w
, RequestedInformation
,
730 pSecurityDescriptor
, nLength
,
735 char filename_a
[MAX_PATH
];
737 if (g_b_init_get_file_security_a
== 0)
739 g_b_init_get_file_security_a
= 1;
740 hm_advapi32
= LoadLibrary ("Advapi32.dll");
741 s_pfn_Get_File_SecurityA
=
742 (GetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
745 if (s_pfn_Get_File_SecurityA
== NULL
)
750 filename_to_ansi (lpFileName
, filename_a
);
751 return (s_pfn_Get_File_SecurityA (filename_a
, RequestedInformation
,
752 pSecurityDescriptor
, nLength
,
758 set_file_security (const char *lpFileName
,
759 SECURITY_INFORMATION SecurityInformation
,
760 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
762 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW
= NULL
;
763 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA
= NULL
;
764 HMODULE hm_advapi32
= NULL
;
765 if (is_windows_9x () == TRUE
)
770 if (w32_unicode_filenames
)
772 wchar_t filename_w
[MAX_PATH
];
774 if (g_b_init_set_file_security_w
== 0)
776 g_b_init_set_file_security_w
= 1;
777 hm_advapi32
= LoadLibrary ("Advapi32.dll");
778 s_pfn_Set_File_SecurityW
=
779 (SetFileSecurityW_Proc
) GetProcAddress (hm_advapi32
,
782 if (s_pfn_Set_File_SecurityW
== NULL
)
787 filename_to_utf16 (lpFileName
, filename_w
);
788 return (s_pfn_Set_File_SecurityW (filename_w
, SecurityInformation
,
789 pSecurityDescriptor
));
793 char filename_a
[MAX_PATH
];
795 if (g_b_init_set_file_security_a
== 0)
797 g_b_init_set_file_security_a
= 1;
798 hm_advapi32
= LoadLibrary ("Advapi32.dll");
799 s_pfn_Set_File_SecurityA
=
800 (SetFileSecurityA_Proc
) GetProcAddress (hm_advapi32
,
803 if (s_pfn_Set_File_SecurityA
== NULL
)
808 filename_to_ansi (lpFileName
, filename_a
);
809 return (s_pfn_Set_File_SecurityA (filename_a
, SecurityInformation
,
810 pSecurityDescriptor
));
815 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
817 LPBOOL lpbOwnerDefaulted
)
819 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner
= NULL
;
820 HMODULE hm_advapi32
= NULL
;
821 if (is_windows_9x () == TRUE
)
826 if (g_b_init_get_security_descriptor_owner
== 0)
828 g_b_init_get_security_descriptor_owner
= 1;
829 hm_advapi32
= LoadLibrary ("Advapi32.dll");
830 s_pfn_Get_Security_Descriptor_Owner
=
831 (GetSecurityDescriptorOwner_Proc
) GetProcAddress (
832 hm_advapi32
, "GetSecurityDescriptorOwner");
834 if (s_pfn_Get_Security_Descriptor_Owner
== NULL
)
839 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor
, pOwner
,
844 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
846 LPBOOL lpbGroupDefaulted
)
848 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group
= NULL
;
849 HMODULE hm_advapi32
= NULL
;
850 if (is_windows_9x () == TRUE
)
855 if (g_b_init_get_security_descriptor_group
== 0)
857 g_b_init_get_security_descriptor_group
= 1;
858 hm_advapi32
= LoadLibrary ("Advapi32.dll");
859 s_pfn_Get_Security_Descriptor_Group
=
860 (GetSecurityDescriptorGroup_Proc
) GetProcAddress (
861 hm_advapi32
, "GetSecurityDescriptorGroup");
863 if (s_pfn_Get_Security_Descriptor_Group
== NULL
)
868 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor
, pGroup
,
873 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor
,
874 LPBOOL lpbDaclPresent
,
876 LPBOOL lpbDaclDefaulted
)
878 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl
= NULL
;
879 HMODULE hm_advapi32
= NULL
;
880 if (is_windows_9x () == TRUE
)
885 if (g_b_init_get_security_descriptor_dacl
== 0)
887 g_b_init_get_security_descriptor_dacl
= 1;
888 hm_advapi32
= LoadLibrary ("Advapi32.dll");
889 s_pfn_Get_Security_Descriptor_Dacl
=
890 (GetSecurityDescriptorDacl_Proc
) GetProcAddress (
891 hm_advapi32
, "GetSecurityDescriptorDacl");
893 if (s_pfn_Get_Security_Descriptor_Dacl
== NULL
)
898 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor
,
899 lpbDaclPresent
, pDacl
,
904 is_valid_sid (PSID sid
)
906 static IsValidSid_Proc s_pfn_Is_Valid_Sid
= NULL
;
907 HMODULE hm_advapi32
= NULL
;
908 if (is_windows_9x () == TRUE
)
912 if (g_b_init_is_valid_sid
== 0)
914 g_b_init_is_valid_sid
= 1;
915 hm_advapi32
= LoadLibrary ("Advapi32.dll");
917 (IsValidSid_Proc
) GetProcAddress (
918 hm_advapi32
, "IsValidSid");
920 if (s_pfn_Is_Valid_Sid
== NULL
)
924 return (s_pfn_Is_Valid_Sid (sid
));
928 equal_sid (PSID sid1
, PSID sid2
)
930 static EqualSid_Proc s_pfn_Equal_Sid
= NULL
;
931 HMODULE hm_advapi32
= NULL
;
932 if (is_windows_9x () == TRUE
)
936 if (g_b_init_equal_sid
== 0)
938 g_b_init_equal_sid
= 1;
939 hm_advapi32
= LoadLibrary ("Advapi32.dll");
941 (EqualSid_Proc
) GetProcAddress (
942 hm_advapi32
, "EqualSid");
944 if (s_pfn_Equal_Sid
== NULL
)
948 return (s_pfn_Equal_Sid (sid1
, sid2
));
952 get_length_sid (PSID sid
)
954 static GetLengthSid_Proc s_pfn_Get_Length_Sid
= NULL
;
955 HMODULE hm_advapi32
= NULL
;
956 if (is_windows_9x () == TRUE
)
960 if (g_b_init_get_length_sid
== 0)
962 g_b_init_get_length_sid
= 1;
963 hm_advapi32
= LoadLibrary ("Advapi32.dll");
964 s_pfn_Get_Length_Sid
=
965 (GetLengthSid_Proc
) GetProcAddress (
966 hm_advapi32
, "GetLengthSid");
968 if (s_pfn_Get_Length_Sid
== NULL
)
972 return (s_pfn_Get_Length_Sid (sid
));
976 copy_sid (DWORD destlen
, PSID dest
, PSID src
)
978 static CopySid_Proc s_pfn_Copy_Sid
= NULL
;
979 HMODULE hm_advapi32
= NULL
;
980 if (is_windows_9x () == TRUE
)
984 if (g_b_init_copy_sid
== 0)
986 g_b_init_copy_sid
= 1;
987 hm_advapi32
= LoadLibrary ("Advapi32.dll");
989 (CopySid_Proc
) GetProcAddress (
990 hm_advapi32
, "CopySid");
992 if (s_pfn_Copy_Sid
== NULL
)
996 return (s_pfn_Copy_Sid (destlen
, dest
, src
));
1000 END: Wrapper functions around OpenProcessToken
1001 and other functions in advapi32.dll that are only
1002 supported in Windows NT / 2k / XP
1006 get_native_system_info (LPSYSTEM_INFO lpSystemInfo
)
1008 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info
= NULL
;
1009 if (is_windows_9x () != TRUE
)
1011 if (g_b_init_get_native_system_info
== 0)
1013 g_b_init_get_native_system_info
= 1;
1014 s_pfn_Get_Native_System_Info
=
1015 (GetNativeSystemInfo_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1016 "GetNativeSystemInfo");
1018 if (s_pfn_Get_Native_System_Info
!= NULL
)
1019 s_pfn_Get_Native_System_Info (lpSystemInfo
);
1022 lpSystemInfo
->dwNumberOfProcessors
= -1;
1026 get_system_times (LPFILETIME lpIdleTime
,
1027 LPFILETIME lpKernelTime
,
1028 LPFILETIME lpUserTime
)
1030 static GetSystemTimes_Proc s_pfn_Get_System_times
= NULL
;
1031 if (is_windows_9x () == TRUE
)
1035 if (g_b_init_get_system_times
== 0)
1037 g_b_init_get_system_times
= 1;
1038 s_pfn_Get_System_times
=
1039 (GetSystemTimes_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1042 if (s_pfn_Get_System_times
== NULL
)
1044 return (s_pfn_Get_System_times (lpIdleTime
, lpKernelTime
, lpUserTime
));
1047 static BOOLEAN WINAPI
1048 create_symbolic_link (LPCSTR lpSymlinkFilename
,
1049 LPCSTR lpTargetFileName
,
1052 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW
= NULL
;
1053 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA
= NULL
;
1056 if (is_windows_9x () == TRUE
)
1061 if (w32_unicode_filenames
)
1063 wchar_t symfn_w
[MAX_PATH
], tgtfn_w
[MAX_PATH
];
1065 if (g_b_init_create_symbolic_link_w
== 0)
1067 g_b_init_create_symbolic_link_w
= 1;
1068 s_pfn_Create_Symbolic_LinkW
=
1069 (CreateSymbolicLinkW_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1070 "CreateSymbolicLinkW");
1072 if (s_pfn_Create_Symbolic_LinkW
== NULL
)
1078 filename_to_utf16 (lpSymlinkFilename
, symfn_w
);
1079 filename_to_utf16 (lpTargetFileName
, tgtfn_w
);
1080 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1081 /* If we were denied creation of the symlink, try again after
1082 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1085 TOKEN_PRIVILEGES priv_current
;
1087 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1090 retval
= s_pfn_Create_Symbolic_LinkW (symfn_w
, tgtfn_w
, dwFlags
);
1091 restore_privilege (&priv_current
);
1098 char symfn_a
[MAX_PATH
], tgtfn_a
[MAX_PATH
];
1100 if (g_b_init_create_symbolic_link_a
== 0)
1102 g_b_init_create_symbolic_link_a
= 1;
1103 s_pfn_Create_Symbolic_LinkA
=
1104 (CreateSymbolicLinkA_Proc
)GetProcAddress (GetModuleHandle ("kernel32.dll"),
1105 "CreateSymbolicLinkA");
1107 if (s_pfn_Create_Symbolic_LinkA
== NULL
)
1113 filename_to_ansi (lpSymlinkFilename
, symfn_a
);
1114 filename_to_ansi (lpTargetFileName
, tgtfn_a
);
1115 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1116 /* If we were denied creation of the symlink, try again after
1117 enabling the SeCreateSymbolicLinkPrivilege for our process. */
1120 TOKEN_PRIVILEGES priv_current
;
1122 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME
, TRUE
,
1125 retval
= s_pfn_Create_Symbolic_LinkA (symfn_a
, tgtfn_a
, dwFlags
);
1126 restore_privilege (&priv_current
);
1135 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor
)
1137 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc
= NULL
;
1139 if (is_windows_9x () == TRUE
)
1145 if (g_b_init_is_valid_security_descriptor
== 0)
1147 g_b_init_is_valid_security_descriptor
= 1;
1148 s_pfn_Is_Valid_Security_Descriptor_Proc
=
1149 (IsValidSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1150 "IsValidSecurityDescriptor");
1152 if (s_pfn_Is_Valid_Security_Descriptor_Proc
== NULL
)
1158 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor
);
1162 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor
,
1163 DWORD RequestedStringSDRevision
,
1164 SECURITY_INFORMATION SecurityInformation
,
1165 LPTSTR
*StringSecurityDescriptor
,
1166 PULONG StringSecurityDescriptorLen
)
1168 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL
= NULL
;
1171 if (is_windows_9x () == TRUE
)
1177 if (g_b_init_convert_sd_to_sddl
== 0)
1179 g_b_init_convert_sd_to_sddl
= 1;
1181 s_pfn_Convert_SD_To_SDDL
=
1182 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1183 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1185 s_pfn_Convert_SD_To_SDDL
=
1186 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1187 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1190 if (s_pfn_Convert_SD_To_SDDL
== NULL
)
1196 retval
= s_pfn_Convert_SD_To_SDDL (SecurityDescriptor
,
1197 RequestedStringSDRevision
,
1198 SecurityInformation
,
1199 StringSecurityDescriptor
,
1200 StringSecurityDescriptorLen
);
1206 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor
,
1207 DWORD StringSDRevision
,
1208 PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
1209 PULONG SecurityDescriptorSize
)
1211 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD
= NULL
;
1214 if (is_windows_9x () == TRUE
)
1220 if (g_b_init_convert_sddl_to_sd
== 0)
1222 g_b_init_convert_sddl_to_sd
= 1;
1224 s_pfn_Convert_SDDL_To_SD
=
1225 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1226 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1228 s_pfn_Convert_SDDL_To_SD
=
1229 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc
)GetProcAddress (GetModuleHandle ("Advapi32.dll"),
1230 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1233 if (s_pfn_Convert_SDDL_To_SD
== NULL
)
1239 retval
= s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor
,
1242 SecurityDescriptorSize
);
1248 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo
, PULONG pOutBufLen
)
1250 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info
= NULL
;
1251 HMODULE hm_iphlpapi
= NULL
;
1253 if (is_windows_9x () == TRUE
)
1254 return ERROR_NOT_SUPPORTED
;
1256 if (g_b_init_get_adapters_info
== 0)
1258 g_b_init_get_adapters_info
= 1;
1259 hm_iphlpapi
= LoadLibrary ("Iphlpapi.dll");
1261 s_pfn_Get_Adapters_Info
= (GetAdaptersInfo_Proc
)
1262 GetProcAddress (hm_iphlpapi
, "GetAdaptersInfo");
1264 if (s_pfn_Get_Adapters_Info
== NULL
)
1265 return ERROR_NOT_SUPPORTED
;
1266 return s_pfn_Get_Adapters_Info (pAdapterInfo
, pOutBufLen
);
1271 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
1272 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
1274 This is called from alloc.c:valid_pointer_p. */
1276 w32_valid_pointer_p (void *p
, int size
)
1279 HANDLE h
= OpenProcess (PROCESS_VM_READ
, FALSE
, GetCurrentProcessId ());
1283 unsigned char *buf
= alloca (size
);
1284 int retval
= ReadProcessMemory (h
, p
, buf
, size
, &done
);
1295 /* Here's an overview of how the Windows build supports file names
1296 that cannot be encoded by the current system codepage.
1298 From the POV of Lisp and layers of C code above the functions here,
1299 Emacs on Windows pretends that its file names are encoded in UTF-8;
1300 see encode_file and decode_file on coding.c. Any file name that is
1301 passed as a unibyte string to C functions defined here is assumed
1302 to be in UTF-8 encoding. Any file name returned by functions
1303 defined here must be in UTF-8 encoding, with only a few exceptions
1304 reserved for a couple of special cases. (Be sure to use
1305 MAX_UTF8_PATH for char arrays that store UTF-8 encoded file names,
1306 as they can be much longer than MAX_PATH!)
1308 The UTF-8 encoded file names cannot be passed to system APIs, as
1309 Windows does not support that. Therefore, they are converted
1310 either to UTF-16 or to the ANSI codepage, depending on the value of
1311 w32-unicode-filenames, before calling any system APIs or CRT library
1312 functions. The default value of that variable is determined by the
1313 OS on which Emacs runs: nil on Windows 9X and t otherwise, but the
1314 user can change that default (although I don't see why would she
1317 The 4 functions defined below, filename_to_utf16, filename_to_ansi,
1318 filename_from_utf16, and filename_from_ansi, are the workhorses of
1319 these conversions. They rely on Windows native APIs
1320 MultiByteToWideChar and WideCharToMultiByte; we cannot use
1321 functions from coding.c here, because they allocate memory, which
1322 is a bad idea on the level of libc, which is what the functions
1323 here emulate. (If you worry about performance due to constant
1324 conversion back and forth from UTF-8 to UTF-16, then don't: first,
1325 it was measured to take only a few microseconds on a not-so-fast
1326 machine, and second, that's exactly what the ANSI APIs we used
1327 before do anyway, because they are just thin wrappers around the
1330 The variables file-name-coding-system and default-file-name-coding-system
1331 still exist, but are actually used only when a file name needs to
1332 be converted to the ANSI codepage. This happens all the time when
1333 w32-unicode-filenames is nil, but can also happen from time to time
1334 when it is t. Otherwise, these variables have no effect on file-name
1335 encoding when w32-unicode-filenames is t; this is similar to
1336 selection-coding-system.
1338 This arrangement works very well, but it has a few gotchas and
1341 . Lisp code that encodes or decodes file names manually should
1342 normally use 'utf-8' as the coding-system on Windows,
1343 disregarding file-name-coding-system. This is a somewhat
1344 unpleasant consequence, but it cannot be avoided. Fortunately,
1345 very few Lisp packages need to do that.
1347 More generally, passing to library functions (e.g., fopen or
1348 opendir) file names already encoded in the ANSI codepage is
1349 explicitly *verboten*, as all those functions, as shadowed and
1350 emulated here, assume they will receive UTF-8 encoded file names.
1352 For the same reasons, no CRT function or Win32 API can be called
1353 directly in Emacs sources, without either converting the file
1354 name sfrom UTF-8 to either UTF-16 or ANSI codepage, or going
1355 through some shadowing function defined here.
1357 . Environment variables stored in Vprocess_environment are encoded
1358 in the ANSI codepage, so if getenv/egetenv is used for a variable
1359 whose value is a file name or a list of directories, it needs to
1360 be converted to UTF-8, before it is used as argument to functions
1361 or decoded into a Lisp string.
1363 . File names passed to external libraries, like the image libraries
1364 and GnuTLS, need special handling. These libraries generally
1365 don't support UTF-16 or UTF-8 file names, so they must get file
1366 names encoded in the ANSI codepage. To facilitate using these
1367 libraries with file names that are not encodable in the ANSI
1368 codepage, use the function ansi_encode_filename, which will try
1369 to use the short 8+3 alias of a file name if that file name is
1370 not encodable in the ANSI codepage. See image.c and gnutls.c for
1371 examples of how this should be done.
1373 . Running subprocesses in non-ASCII directories and with non-ASCII
1374 file arguments is limited to the current codepage (even though
1375 Emacs is perfectly capable of finding an executable program file
1376 even in a directory whose name cannot be encoded in the current
1377 codepage). This is because the command-line arguments are
1378 encoded _before_ they get to the w32-specific level, and the
1379 encoding is not known in advance (it doesn't have to be the
1380 current ANSI codepage), so w32proc.c functions cannot re-encode
1381 them in UTF-16. This should be fixed, but will also require
1382 changes in cmdproxy. The current limitation is not terribly bad
1383 anyway, since very few, if any, Windows console programs that are
1384 likely to be invoked by Emacs support UTF-16 encoded command
1387 . For similar reasons, server.el and emacsclient are also limited
1388 to the current ANSI codepage for now.
1390 . Emacs itself can only handle command-line arguments encoded in
1391 the current codepage.
1393 . Turning on w32-unicode-filename on Windows 9X (if it at all
1394 works) requires UNICOWS.DLL, which is currently loaded only in a
1399 /* Converting file names from UTF-8 to either UTF-16 or the ANSI
1400 codepage defined by file-name-coding-system. */
1402 /* Current codepage for encoding file names. */
1403 static int file_name_codepage
;
1405 /* Produce a Windows ANSI codepage suitable for encoding file names.
1406 Return the information about that codepage in CP_INFO. */
1408 codepage_for_filenames (CPINFO
*cp_info
)
1410 /* A simple cache to avoid calling GetCPInfo every time we need to
1411 encode/decode a file name. The file-name encoding is not
1412 supposed to be changed too frequently, if ever. */
1413 static Lisp_Object last_file_name_encoding
;
1415 Lisp_Object current_encoding
;
1417 current_encoding
= Vfile_name_coding_system
;
1418 if (NILP (current_encoding
))
1419 current_encoding
= Vdefault_file_name_coding_system
;
1421 if (!EQ (last_file_name_encoding
, current_encoding
))
1423 /* Default to the current ANSI codepage. */
1424 file_name_codepage
= w32_ansi_code_page
;
1426 if (NILP (current_encoding
))
1428 char *cpname
= SDATA (SYMBOL_NAME (current_encoding
));
1429 char *cp
= NULL
, *end
;
1432 if (strncmp (cpname
, "cp", 2) == 0)
1434 else if (strncmp (cpname
, "windows-", 8) == 0)
1440 cpnum
= strtol (cp
, &end
, 10);
1441 if (cpnum
&& *end
== '\0' && end
- cp
>= 2)
1442 file_name_codepage
= cpnum
;
1446 if (!file_name_codepage
)
1447 file_name_codepage
= CP_ACP
; /* CP_ACP = 0, but let's not assume that */
1449 if (!GetCPInfo (file_name_codepage
, &cp
))
1451 file_name_codepage
= CP_ACP
;
1452 if (!GetCPInfo (file_name_codepage
, &cp
))
1459 return file_name_codepage
;
1463 filename_to_utf16 (const char *fn_in
, wchar_t *fn_out
)
1465 int result
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1470 DWORD err
= GetLastError ();
1474 case ERROR_INVALID_FLAGS
:
1475 case ERROR_INVALID_PARAMETER
:
1478 case ERROR_INSUFFICIENT_BUFFER
:
1479 case ERROR_NO_UNICODE_TRANSLATION
:
1490 filename_from_utf16 (const wchar_t *fn_in
, char *fn_out
)
1492 int result
= WideCharToMultiByte (CP_UTF8
, 0, fn_in
, -1,
1493 fn_out
, MAX_UTF8_PATH
, NULL
, NULL
);
1497 DWORD err
= GetLastError ();
1501 case ERROR_INVALID_FLAGS
:
1502 case ERROR_INVALID_PARAMETER
:
1505 case ERROR_INSUFFICIENT_BUFFER
:
1506 case ERROR_NO_UNICODE_TRANSLATION
:
1517 filename_to_ansi (const char *fn_in
, char *fn_out
)
1519 wchar_t fn_utf16
[MAX_PATH
];
1521 if (filename_to_utf16 (fn_in
, fn_utf16
) == 0)
1524 int codepage
= codepage_for_filenames (NULL
);
1526 result
= WideCharToMultiByte (codepage
, 0, fn_utf16
, -1,
1527 fn_out
, MAX_PATH
, NULL
, NULL
);
1530 DWORD err
= GetLastError ();
1534 case ERROR_INVALID_FLAGS
:
1535 case ERROR_INVALID_PARAMETER
:
1538 case ERROR_INSUFFICIENT_BUFFER
:
1539 case ERROR_NO_UNICODE_TRANSLATION
:
1552 filename_from_ansi (const char *fn_in
, char *fn_out
)
1554 wchar_t fn_utf16
[MAX_PATH
];
1555 int codepage
= codepage_for_filenames (NULL
);
1556 int result
= MultiByteToWideChar (codepage
, MB_ERR_INVALID_CHARS
, fn_in
, -1,
1557 fn_utf16
, MAX_PATH
);
1561 DWORD err
= GetLastError ();
1565 case ERROR_INVALID_FLAGS
:
1566 case ERROR_INVALID_PARAMETER
:
1569 case ERROR_INSUFFICIENT_BUFFER
:
1570 case ERROR_NO_UNICODE_TRANSLATION
:
1577 return filename_from_utf16 (fn_utf16
, fn_out
);
1582 /* The directory where we started, in UTF-8. */
1583 static char startup_dir
[MAX_UTF8_PATH
];
1585 /* Get the current working directory. */
1587 getcwd (char *dir
, int dirsize
)
1594 if (dirsize
<= strlen (startup_dir
))
1600 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
1604 /* Emacs doesn't actually change directory itself, it stays in the
1605 same directory where it was started. */
1606 strcpy (dir
, startup_dir
);
1611 /* Emulate getloadavg. */
1613 struct load_sample
{
1620 /* Number of processors on this machine. */
1621 static unsigned num_of_processors
;
1623 /* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
1624 static struct load_sample samples
[16*60];
1625 static int first_idx
= -1, last_idx
= -1;
1626 static int max_idx
= sizeof (samples
) / sizeof (samples
[0]);
1631 int next_idx
= from
+ 1;
1633 if (next_idx
>= max_idx
)
1642 int prev_idx
= from
- 1;
1645 prev_idx
= max_idx
- 1;
1651 sample_system_load (ULONGLONG
*idle
, ULONGLONG
*kernel
, ULONGLONG
*user
)
1653 SYSTEM_INFO sysinfo
;
1654 FILETIME ft_idle
, ft_user
, ft_kernel
;
1656 /* Initialize the number of processors on this machine. */
1657 if (num_of_processors
<= 0)
1659 get_native_system_info (&sysinfo
);
1660 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1661 if (num_of_processors
<= 0)
1663 GetSystemInfo (&sysinfo
);
1664 num_of_processors
= sysinfo
.dwNumberOfProcessors
;
1666 if (num_of_processors
<= 0)
1667 num_of_processors
= 1;
1670 /* TODO: Take into account threads that are ready to run, by
1671 sampling the "\System\Processor Queue Length" performance
1672 counter. The code below accounts only for threads that are
1673 actually running. */
1675 if (get_system_times (&ft_idle
, &ft_kernel
, &ft_user
))
1677 ULARGE_INTEGER uidle
, ukernel
, uuser
;
1679 memcpy (&uidle
, &ft_idle
, sizeof (ft_idle
));
1680 memcpy (&ukernel
, &ft_kernel
, sizeof (ft_kernel
));
1681 memcpy (&uuser
, &ft_user
, sizeof (ft_user
));
1682 *idle
= uidle
.QuadPart
;
1683 *kernel
= ukernel
.QuadPart
;
1684 *user
= uuser
.QuadPart
;
1694 /* Produce the load average for a given time interval, using the
1695 samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
1696 1-minute, 5-minute, or 15-minute average, respectively. */
1700 double retval
= -1.0;
1703 double span
= (which
== 0 ? 1.0 : (which
== 1 ? 5.0 : 15.0)) * 60;
1704 time_t now
= samples
[last_idx
].sample_time
;
1706 if (first_idx
!= last_idx
)
1708 for (idx
= buf_prev (last_idx
); ; idx
= buf_prev (idx
))
1710 tdiff
= difftime (now
, samples
[idx
].sample_time
);
1711 if (tdiff
>= span
- 2*DBL_EPSILON
*now
)
1714 samples
[last_idx
].kernel
+ samples
[last_idx
].user
1715 - (samples
[idx
].kernel
+ samples
[idx
].user
);
1716 long double idl
= samples
[last_idx
].idle
- samples
[idx
].idle
;
1718 retval
= (1.0 - idl
/ sys
) * num_of_processors
;
1721 if (idx
== first_idx
)
1730 getloadavg (double loadavg
[], int nelem
)
1733 ULONGLONG idle
, kernel
, user
;
1734 time_t now
= time (NULL
);
1736 /* If system time jumped back for some reason, delete all samples
1737 whose time is later than the current wall-clock time. This
1738 prevents load average figures from becoming frozen for prolonged
1739 periods of time, when system time is reset backwards. */
1742 while (difftime (now
, samples
[last_idx
].sample_time
) < -1.0)
1744 if (last_idx
== first_idx
)
1746 first_idx
= last_idx
= -1;
1749 last_idx
= buf_prev (last_idx
);
1753 /* Store another sample. We ignore samples that are less than 1 sec
1756 || (difftime (now
, samples
[last_idx
].sample_time
)
1757 >= 1.0 - 2*DBL_EPSILON
*now
))
1759 sample_system_load (&idle
, &kernel
, &user
);
1760 last_idx
= buf_next (last_idx
);
1761 samples
[last_idx
].sample_time
= now
;
1762 samples
[last_idx
].idle
= idle
;
1763 samples
[last_idx
].kernel
= kernel
;
1764 samples
[last_idx
].user
= user
;
1765 /* If the buffer has more that 15 min worth of samples, discard
1767 if (first_idx
== -1)
1768 first_idx
= last_idx
;
1769 while (first_idx
!= last_idx
1770 && (difftime (now
, samples
[first_idx
].sample_time
)
1771 >= 15.0*60 + 2*DBL_EPSILON
*now
))
1772 first_idx
= buf_next (first_idx
);
1775 for (elem
= 0; elem
< nelem
; elem
++)
1777 double avg
= getavg (elem
);
1781 loadavg
[elem
] = avg
;
1787 /* Emulate getpwuid, getpwnam and others. */
1789 #define PASSWD_FIELD_SIZE 256
1791 static char dflt_passwd_name
[PASSWD_FIELD_SIZE
];
1792 static char dflt_passwd_passwd
[PASSWD_FIELD_SIZE
];
1793 static char dflt_passwd_gecos
[PASSWD_FIELD_SIZE
];
1794 static char dflt_passwd_dir
[MAX_UTF8_PATH
];
1795 static char dflt_passwd_shell
[MAX_UTF8_PATH
];
1797 static struct passwd dflt_passwd
=
1809 static char dflt_group_name
[GNLEN
+1];
1811 static struct group dflt_group
=
1813 /* When group information is not available, we return this as the
1814 group for all files. */
1822 return dflt_passwd
.pw_uid
;
1828 /* I could imagine arguing for checking to see whether the user is
1829 in the Administrators group and returning a UID of 0 for that
1830 case, but I don't know how wise that would be in the long run. */
1837 return dflt_passwd
.pw_gid
;
1847 getpwuid (unsigned uid
)
1849 if (uid
== dflt_passwd
.pw_uid
)
1850 return &dflt_passwd
;
1855 getgrgid (gid_t gid
)
1861 getpwnam (char *name
)
1865 pw
= getpwuid (getuid ());
1869 if (xstrcasecmp (name
, pw
->pw_name
))
1876 init_user_info (void)
1878 /* Find the user's real name by opening the process token and
1879 looking up the name associated with the user-sid in that token.
1881 Use the relative portion of the identifier authority value from
1882 the user-sid as the user id value (same for group id using the
1883 primary group sid from the process token). */
1885 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
1886 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
1887 DWORD glength
= sizeof (gname
);
1888 HANDLE token
= NULL
;
1889 SID_NAME_USE user_type
;
1890 unsigned char *buf
= NULL
;
1892 TOKEN_USER user_token
;
1893 TOKEN_PRIMARY_GROUP group_token
;
1896 result
= open_process_token (GetCurrentProcess (), TOKEN_QUERY
, &token
);
1899 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
1900 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1902 buf
= xmalloc (blen
);
1903 result
= get_token_information (token
, TokenUser
,
1904 (LPVOID
)buf
, blen
, &needed
);
1907 memcpy (&user_token
, buf
, sizeof (user_token
));
1908 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
1910 domain
, &dlength
, &user_type
);
1918 strcpy (dflt_passwd
.pw_name
, uname
);
1919 /* Determine a reasonable uid value. */
1920 if (xstrcasecmp ("administrator", uname
) == 0)
1922 dflt_passwd
.pw_uid
= 500; /* well-known Administrator uid */
1923 dflt_passwd
.pw_gid
= 513; /* well-known None gid */
1927 /* Use the last sub-authority value of the RID, the relative
1928 portion of the SID, as user/group ID. */
1929 dflt_passwd
.pw_uid
= get_rid (user_token
.User
.Sid
);
1931 /* Get group id and name. */
1932 result
= get_token_information (token
, TokenPrimaryGroup
,
1933 (LPVOID
)buf
, blen
, &needed
);
1934 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
1936 buf
= xrealloc (buf
, blen
= needed
);
1937 result
= get_token_information (token
, TokenPrimaryGroup
,
1938 (LPVOID
)buf
, blen
, &needed
);
1942 memcpy (&group_token
, buf
, sizeof (group_token
));
1943 dflt_passwd
.pw_gid
= get_rid (group_token
.PrimaryGroup
);
1944 dlength
= sizeof (domain
);
1945 /* If we can get at the real Primary Group name, use that.
1946 Otherwise, the default group name was already set to
1947 "None" in globals_of_w32. */
1948 if (lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
1949 gname
, &glength
, NULL
, &dlength
,
1951 strcpy (dflt_group_name
, gname
);
1954 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1957 /* If security calls are not supported (presumably because we
1958 are running under Windows 9X), fallback to this: */
1959 else if (GetUserName (uname
, &ulength
))
1961 strcpy (dflt_passwd
.pw_name
, uname
);
1962 if (xstrcasecmp ("administrator", uname
) == 0)
1963 dflt_passwd
.pw_uid
= 0;
1965 dflt_passwd
.pw_uid
= 123;
1966 dflt_passwd
.pw_gid
= dflt_passwd
.pw_uid
;
1970 strcpy (dflt_passwd
.pw_name
, "unknown");
1971 dflt_passwd
.pw_uid
= 123;
1972 dflt_passwd
.pw_gid
= 123;
1974 dflt_group
.gr_gid
= dflt_passwd
.pw_gid
;
1976 /* Set dir and shell from environment variables. */
1977 if (w32_unicode_filenames
)
1979 wchar_t *home
= _wgetenv (L
"HOME");
1980 wchar_t *shell
= _wgetenv (L
"SHELL");
1982 /* Ensure HOME and SHELL are defined. */
1987 filename_from_utf16 (home
, dflt_passwd
.pw_dir
);
1988 filename_from_utf16 (shell
, dflt_passwd
.pw_shell
);
1992 char *home
= getenv ("HOME");
1993 char *shell
= getenv ("SHELL");
1999 filename_from_ansi (home
, dflt_passwd
.pw_dir
);
2000 filename_from_ansi (shell
, dflt_passwd
.pw_shell
);
2005 CloseHandle (token
);
2011 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
2012 return ((rand () << 15) | rand ());
2021 /* Return the maximum length in bytes of a multibyte character
2022 sequence encoded in the current ANSI codepage. This is required to
2023 correctly walk the encoded file names one character at a time. */
2025 max_filename_mbslen (void)
2029 codepage_for_filenames (&cp_info
);
2030 return cp_info
.MaxCharSize
;
2033 /* Normalize filename by converting in-place all of its path
2034 separators to the separator specified by PATH_SEP. */
2037 normalize_filename (register char *fp
, char path_sep
)
2041 /* Always lower-case drive letters a-z, even if the filesystem
2042 preserves case in filenames.
2043 This is so filenames can be compared by string comparison
2044 functions that are case-sensitive. Even case-preserving filesystems
2045 do not distinguish case in drive letters. */
2048 if (*p2
== ':' && *fp
>= 'A' && *fp
<= 'Z')
2056 if ((*fp
== '/' || *fp
== '\\') && *fp
!= path_sep
)
2062 /* Destructively turn backslashes into slashes. */
2064 dostounix_filename (register char *p
)
2066 normalize_filename (p
, '/');
2069 /* Destructively turn slashes into backslashes. */
2071 unixtodos_filename (register char *p
)
2073 normalize_filename (p
, '\\');
2076 /* Remove all CR's that are followed by a LF.
2077 (From msdos.c...probably should figure out a way to share it,
2078 although this code isn't going to ever change.) */
2080 crlf_to_lf (register int n
, register unsigned char *buf
)
2082 unsigned char *np
= buf
;
2083 unsigned char *startp
= buf
;
2084 unsigned char *endp
= buf
+ n
;
2088 while (buf
< endp
- 1)
2092 if (*(++buf
) != 0x0a)
2103 /* Parse the root part of file name, if present. Return length and
2104 optionally store pointer to char after root. */
2106 parse_root (const char * name
, const char ** pPath
)
2108 const char * start
= name
;
2113 /* find the root name of the volume if given */
2114 if (isalpha (name
[0]) && name
[1] == ':')
2116 /* skip past drive specifier */
2118 if (IS_DIRECTORY_SEP (name
[0]))
2121 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
2128 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
2133 if (IS_DIRECTORY_SEP (name
[0]))
2140 return name
- start
;
2143 /* Get long base name for name; name is assumed to be absolute. */
2145 get_long_basename (char * name
, char * buf
, int size
)
2147 HANDLE dir_handle
= INVALID_HANDLE_VALUE
;
2148 char fname_utf8
[MAX_UTF8_PATH
];
2152 /* Must be valid filename, no wild cards or other invalid characters. */
2153 if (strpbrk (name
, "*?|<>\""))
2156 if (w32_unicode_filenames
)
2158 wchar_t fname_utf16
[MAX_PATH
];
2159 WIN32_FIND_DATAW find_data_wide
;
2161 filename_to_utf16 (name
, fname_utf16
);
2162 dir_handle
= FindFirstFileW (fname_utf16
, &find_data_wide
);
2163 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2164 cstatus
= filename_from_utf16 (find_data_wide
.cFileName
, fname_utf8
);
2168 char fname_ansi
[MAX_PATH
];
2169 WIN32_FIND_DATAA find_data_ansi
;
2171 filename_to_ansi (name
, fname_ansi
);
2172 /* If the ANSI name includes ? characters, it is not encodable
2173 in the ANSI codepage. In that case, we deliver the question
2174 marks to the caller; calling FindFirstFileA in this case
2175 could return some unrelated file name in the same
2177 if (_mbspbrk (fname_ansi
, "?"))
2179 /* Find the basename of fname_ansi. */
2180 char *p
= strrchr (fname_ansi
, '\\');
2186 cstatus
= filename_from_ansi (p
, fname_utf8
);
2190 dir_handle
= FindFirstFileA (fname_ansi
, &find_data_ansi
);
2191 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2192 cstatus
= filename_from_ansi (find_data_ansi
.cFileName
, fname_utf8
);
2196 if (cstatus
== 0 && (len
= strlen (fname_utf8
)) < size
)
2197 memcpy (buf
, fname_utf8
, len
+ 1);
2201 if (dir_handle
!= INVALID_HANDLE_VALUE
)
2202 FindClose (dir_handle
);
2207 /* Get long name for file, if possible (assumed to be absolute). */
2209 w32_get_long_filename (char * name
, char * buf
, int size
)
2214 char full
[ MAX_UTF8_PATH
];
2217 len
= strlen (name
);
2218 if (len
>= MAX_UTF8_PATH
)
2221 /* Use local copy for destructive modification. */
2222 memcpy (full
, name
, len
+1);
2223 unixtodos_filename (full
);
2225 /* Copy root part verbatim. */
2226 len
= parse_root (full
, (const char **)&p
);
2227 memcpy (o
, full
, len
);
2232 while (p
!= NULL
&& *p
)
2235 p
= strchr (q
, '\\');
2237 len
= get_long_basename (full
, o
, size
);
2260 w32_get_short_filename (char * name
, char * buf
, int size
)
2262 if (w32_unicode_filenames
)
2264 wchar_t name_utf16
[MAX_PATH
], short_name
[MAX_PATH
];
2265 unsigned int retval
;
2267 filename_to_utf16 (name
, name_utf16
);
2268 retval
= GetShortPathNameW (name_utf16
, short_name
, size
);
2269 if (retval
&& retval
< size
)
2270 filename_from_utf16 (short_name
, buf
);
2275 char name_ansi
[MAX_PATH
];
2277 filename_to_ansi (name
, name_ansi
);
2278 return GetShortPathNameA (name_ansi
, buf
, size
);
2282 /* Re-encode FILENAME, a UTF-8 encoded unibyte string, using the
2283 MS-Windows ANSI codepage. If FILENAME includes characters not
2284 supported by the ANSI codepage, return the 8+3 alias of FILENAME,
2285 if it exists. This is needed because the w32 build wants to
2286 support file names outside of the system locale, but image
2287 libraries typically don't support wide (a.k.a. "Unicode") APIs
2288 required for that. */
2291 ansi_encode_filename (Lisp_Object filename
)
2293 Lisp_Object encoded_filename
;
2294 char fname
[MAX_PATH
];
2296 filename_to_ansi (SSDATA (filename
), fname
);
2297 if (_mbspbrk (fname
, "?"))
2299 char shortname
[MAX_PATH
];
2301 if (w32_get_short_filename (SDATA (filename
), shortname
, MAX_PATH
))
2303 dostounix_filename (shortname
);
2304 encoded_filename
= build_string (shortname
);
2308 encoded_filename
= build_unibyte_string (fname
);
2309 return encoded_filename
;
2313 is_unc_volume (const char *filename
)
2315 const char *ptr
= filename
;
2317 if (!IS_DIRECTORY_SEP (ptr
[0]) || !IS_DIRECTORY_SEP (ptr
[1]) || !ptr
[2])
2320 if (strpbrk (ptr
+ 2, "*?|<>\"\\/"))
2326 /* Emulate the Posix unsetenv. */
2328 unsetenv (const char *name
)
2334 if (name
== NULL
|| *name
== '\0' || strchr (name
, '=') != NULL
)
2339 name_len
= strlen (name
);
2340 /* MS docs says an environment variable cannot be longer than 32K. */
2341 if (name_len
> 32767)
2346 /* It is safe to use 'alloca' with 32K size, since the stack is at
2347 least 2MB, and we set it to 8MB in the link command line. */
2348 var
= alloca (name_len
+ 2);
2349 strncpy (var
, name
, name_len
);
2350 var
[name_len
++] = '=';
2351 var
[name_len
] = '\0';
2352 return _putenv (var
);
2355 /* MS _putenv doesn't support removing a variable when the argument
2356 does not include the '=' character, so we fix that here. */
2358 sys_putenv (char *str
)
2360 const char *const name_end
= strchr (str
, '=');
2362 if (name_end
== NULL
)
2364 /* Remove the variable from the environment. */
2365 return unsetenv (str
);
2368 return _putenv (str
);
2371 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2374 w32_get_resource (char *key
, LPDWORD lpdwtype
)
2377 HKEY hrootkey
= NULL
;
2380 /* Check both the current user and the local machine to see if
2381 we have any resources. */
2383 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2387 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2388 && (lpvalue
= xmalloc (cbData
)) != NULL
2389 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2391 RegCloseKey (hrootkey
);
2397 RegCloseKey (hrootkey
);
2400 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
2404 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
2405 && (lpvalue
= xmalloc (cbData
)) != NULL
2406 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
2408 RegCloseKey (hrootkey
);
2414 RegCloseKey (hrootkey
);
2420 /* The argv[] array holds ANSI-encoded strings, and so this function
2421 works with ANS_encoded strings. */
2423 init_environment (char ** argv
)
2425 static const char * const tempdirs
[] = {
2426 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2431 const int imax
= sizeof (tempdirs
) / sizeof (tempdirs
[0]);
2433 /* Implementation note: This function explicitly works with ANSI
2434 file names, not with UTF-8 encoded file names. This is because
2435 this function pushes variables into the Emacs's environment, and
2436 the environment variables are always assumed to be in the
2437 locale-specific encoding. Do NOT call any functions that accept
2438 UTF-8 file names from this function! */
2440 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
2441 temporary files and assume "/tmp" if $TMPDIR is unset, which
2442 will break on DOS/Windows. Refuse to work if we cannot find
2443 a directory, not even "c:/", usable for that purpose. */
2444 for (i
= 0; i
< imax
; i
++)
2446 const char *tmp
= tempdirs
[i
];
2449 tmp
= getenv (tmp
+ 1);
2450 /* Note that `access' can lie to us if the directory resides on a
2451 read-only filesystem, like CD-ROM or a write-protected floppy.
2452 The only way to be really sure is to actually create a file and
2453 see if it succeeds. But I think that's too much to ask. */
2455 /* MSVCRT's _access crashes with D_OK, so we use our replacement. */
2456 if (tmp
&& sys_access (tmp
, D_OK
) == 0)
2458 char * var
= alloca (strlen (tmp
) + 8);
2459 sprintf (var
, "TMPDIR=%s", tmp
);
2460 _putenv (strdup (var
));
2467 Fcons (build_string ("no usable temporary directories found!!"),
2469 "While setting TMPDIR: ");
2471 /* Check for environment variables and use registry settings if they
2472 don't exist. Fallback on default values where applicable. */
2477 char locale_name
[32];
2478 char default_home
[MAX_PATH
];
2481 static const struct env_entry
2487 /* If the default value is NULL, we will use the value from the
2488 outside environment or the Registry, but will not push the
2489 variable into the Emacs environment if it is defined neither
2490 in the Registry nor in the outside environment. */
2492 {"PRELOAD_WINSOCK", NULL
},
2493 {"emacs_dir", "C:/emacs"},
2494 {"EMACSLOADPATH", NULL
},
2495 {"SHELL", "cmdproxy.exe"}, /* perhaps it is somewhere on PATH */
2496 {"EMACSDATA", NULL
},
2497 {"EMACSPATH", NULL
},
2504 #define N_ENV_VARS sizeof (dflt_envvars)/sizeof (dflt_envvars[0])
2506 /* We need to copy dflt_envvars[] and work on the copy because we
2507 don't want the dumped Emacs to inherit the values of
2508 environment variables we saw during dumping (which could be on
2509 a different system). The defaults above must be left intact. */
2510 struct env_entry env_vars
[N_ENV_VARS
];
2512 for (i
= 0; i
< N_ENV_VARS
; i
++)
2513 env_vars
[i
] = dflt_envvars
[i
];
2515 /* For backwards compatibility, check if a .emacs file exists in C:/
2516 If not, then we can try to default to the appdata directory under the
2517 user's profile, which is more likely to be writable. */
2518 if (sys_access ("C:/.emacs", F_OK
) != 0)
2520 HRESULT profile_result
;
2521 /* Dynamically load ShGetFolderPath, as it won't exist on versions
2522 of Windows 95 and NT4 that have not been updated to include
2524 ShGetFolderPath_fn get_folder_path
;
2525 get_folder_path
= (ShGetFolderPath_fn
)
2526 GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
2528 if (get_folder_path
!= NULL
)
2530 profile_result
= get_folder_path (NULL
, CSIDL_APPDATA
, NULL
,
2533 /* If we can't get the appdata dir, revert to old behavior. */
2534 if (profile_result
== S_OK
)
2536 env_vars
[0].def_value
= default_home
;
2542 /* Get default locale info and use it for LANG. */
2543 if (GetLocaleInfo (LOCALE_USER_DEFAULT
,
2544 LOCALE_SABBREVLANGNAME
| LOCALE_USE_CP_ACP
,
2545 locale_name
, sizeof (locale_name
)))
2547 for (i
= 0; i
< N_ENV_VARS
; i
++)
2549 if (strcmp (env_vars
[i
].name
, "LANG") == 0)
2551 env_vars
[i
].def_value
= locale_name
;
2557 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
2559 /* Treat emacs_dir specially: set it unconditionally based on our
2563 char modname
[MAX_PATH
];
2565 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2567 if ((p
= _mbsrchr (modname
, '\\')) == NULL
)
2571 if ((p
= _mbsrchr (modname
, '\\'))
2572 /* From bin means installed Emacs, from src means uninstalled. */
2573 && (xstrcasecmp (p
, "\\bin") == 0 || xstrcasecmp (p
, "\\src") == 0))
2575 char buf
[SET_ENV_BUF_SIZE
];
2576 int within_build_tree
= xstrcasecmp (p
, "\\src") == 0;
2579 for (p
= modname
; *p
; p
= CharNext (p
))
2580 if (*p
== '\\') *p
= '/';
2582 _snprintf (buf
, sizeof (buf
)-1, "emacs_dir=%s", modname
);
2583 _putenv (strdup (buf
));
2584 /* If we are running from the Posix-like build tree, define
2585 SHELL to point to our own cmdproxy. The loop below will
2586 then disregard PATH_EXEC and the default value. */
2587 if (within_build_tree
)
2589 _snprintf (buf
, sizeof (buf
) - 1,
2590 "SHELL=%s/nt/cmdproxy.exe", modname
);
2591 _putenv (strdup (buf
));
2596 for (i
= 0; i
< N_ENV_VARS
; i
++)
2598 if (!getenv (env_vars
[i
].name
))
2601 char bufc
[SET_ENV_BUF_SIZE
];
2603 if ((lpval
= w32_get_resource (env_vars
[i
].name
, &dwType
)) == NULL
2604 /* Also ignore empty environment variables. */
2609 if (strcmp (env_vars
[i
].name
, "SHELL") == 0)
2611 /* Look for cmdproxy.exe in every directory in
2612 PATH_EXEC. FIXME: This does not find cmdproxy
2613 in nt/ when we run uninstalled. */
2614 char fname
[MAX_PATH
];
2615 const char *pstart
= PATH_EXEC
, *pend
;
2618 pend
= _mbschr (pstart
, ';');
2620 pend
= pstart
+ strlen (pstart
);
2621 /* Be defensive against series of ;;; characters. */
2624 strncpy (fname
, pstart
, pend
- pstart
);
2625 fname
[pend
- pstart
] = '/';
2626 strcpy (&fname
[pend
- pstart
+ 1], "cmdproxy.exe");
2627 ExpandEnvironmentStrings ((LPSTR
) fname
, bufc
,
2629 if (sys_access (bufc
, F_OK
) == 0)
2642 /* If not found in any directory, use the
2643 default as the last resort. */
2644 lpval
= env_vars
[i
].def_value
;
2645 dwType
= REG_EXPAND_SZ
;
2651 lpval
= env_vars
[i
].def_value
;
2652 dwType
= REG_EXPAND_SZ
;
2654 if (strcmp (env_vars
[i
].name
, "HOME") == 0 && !appdata
)
2655 Vdelayed_warnings_list
2656 = Fcons (listn (CONSTYPE_HEAP
, 2,
2657 intern ("initialization"),
2658 build_string ("Setting HOME to C:\\ by default is deprecated")),
2659 Vdelayed_warnings_list
);
2664 char buf1
[SET_ENV_BUF_SIZE
], buf2
[SET_ENV_BUF_SIZE
];
2666 if (dwType
== REG_EXPAND_SZ
)
2667 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, sizeof (buf1
));
2668 else if (dwType
== REG_SZ
)
2669 strcpy (buf1
, lpval
);
2670 if (dwType
== REG_EXPAND_SZ
|| dwType
== REG_SZ
)
2672 _snprintf (buf2
, sizeof (buf2
)-1, "%s=%s", env_vars
[i
].name
,
2674 _putenv (strdup (buf2
));
2684 /* Rebuild system configuration to reflect invoking system. */
2685 Vsystem_configuration
= build_string (EMACS_CONFIGURATION
);
2687 /* Another special case: on NT, the PATH variable is actually named
2688 "Path" although cmd.exe (perhaps NT itself) arranges for
2689 environment variable lookup and setting to be case insensitive.
2690 However, Emacs assumes a fully case sensitive environment, so we
2691 need to change "Path" to "PATH" to match the expectations of
2692 various elisp packages. We do this by the sneaky method of
2693 modifying the string in the C runtime environ entry.
2695 The same applies to COMSPEC. */
2699 for (envp
= environ
; *envp
; envp
++)
2700 if (_strnicmp (*envp
, "PATH=", 5) == 0)
2701 memcpy (*envp
, "PATH=", 5);
2702 else if (_strnicmp (*envp
, "COMSPEC=", 8) == 0)
2703 memcpy (*envp
, "COMSPEC=", 8);
2706 /* Remember the initial working directory for getcwd. */
2707 /* FIXME: Do we need to resolve possible symlinks in startup_dir?
2708 Does it matter anywhere in Emacs? */
2709 if (w32_unicode_filenames
)
2711 wchar_t wstartup_dir
[MAX_PATH
];
2713 if (!GetCurrentDirectoryW (MAX_PATH
, wstartup_dir
))
2715 filename_from_utf16 (wstartup_dir
, startup_dir
);
2719 char astartup_dir
[MAX_PATH
];
2721 if (!GetCurrentDirectoryA (MAX_PATH
, astartup_dir
))
2723 filename_from_ansi (astartup_dir
, startup_dir
);
2727 static char modname
[MAX_PATH
];
2729 if (!GetModuleFileNameA (NULL
, modname
, MAX_PATH
))
2734 /* Determine if there is a middle mouse button, to allow parse_button
2735 to decide whether right mouse events should be mouse-2 or
2737 w32_num_mouse_buttons
= GetSystemMetrics (SM_CMOUSEBUTTONS
);
2742 /* Called from expand-file-name when default-directory is not a string. */
2745 emacs_root_dir (void)
2747 static char root_dir
[MAX_UTF8_PATH
];
2750 p
= getenv ("emacs_dir");
2753 filename_from_ansi (p
, root_dir
);
2754 root_dir
[parse_root (root_dir
, NULL
)] = '\0';
2755 dostounix_filename (root_dir
);
2759 #include <sys/timeb.h>
2761 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2763 gettimeofday (struct timeval
*__restrict tv
, struct timezone
*__restrict tz
)
2768 tv
->tv_sec
= tb
.time
;
2769 tv
->tv_usec
= tb
.millitm
* 1000L;
2770 /* Implementation note: _ftime sometimes doesn't update the dstflag
2771 according to the new timezone when the system timezone is
2772 changed. We could fix that by using GetSystemTime and
2773 GetTimeZoneInformation, but that doesn't seem necessary, since
2774 Emacs always calls gettimeofday with the 2nd argument NULL (see
2775 current_emacs_time). */
2778 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
2779 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
2784 /* Emulate fdutimens. */
2786 /* Set the access and modification time stamps of FD (a.k.a. FILE) to be
2787 TIMESPEC[0] and TIMESPEC[1], respectively.
2788 FD must be either negative -- in which case it is ignored --
2789 or a file descriptor that is open on FILE.
2790 If FD is nonnegative, then FILE can be NULL, which means
2791 use just futimes instead of utimes.
2792 If TIMESPEC is null, FAIL.
2793 Return 0 on success, -1 (setting errno) on failure. */
2796 fdutimens (int fd
, char const *file
, struct timespec
const timespec
[2])
2803 if (fd
< 0 && !file
)
2808 /* _futime's prototype defines 2nd arg as having the type 'struct
2809 _utimbuf', while utime needs to accept 'struct utimbuf' for
2810 compatibility with Posix. So we need to use 2 different (but
2811 equivalent) types to avoid compiler warnings, sigh. */
2814 struct _utimbuf _ut
;
2816 _ut
.actime
= timespec
[0].tv_sec
;
2817 _ut
.modtime
= timespec
[1].tv_sec
;
2818 return _futime (fd
, &_ut
);
2824 ut
.actime
= timespec
[0].tv_sec
;
2825 ut
.modtime
= timespec
[1].tv_sec
;
2826 /* Call 'utime', which is implemented below, not the MS library
2827 function, which fails on directories. */
2828 return utime (file
, &ut
);
2833 /* ------------------------------------------------------------------------- */
2834 /* IO support and wrapper functions for the Windows API. */
2835 /* ------------------------------------------------------------------------- */
2837 /* Place a wrapper around the MSVC version of ctime. It returns NULL
2838 on network directories, so we handle that case here.
2839 (Ulrich Leodolter, 1/11/95). */
2841 sys_ctime (const time_t *t
)
2843 char *str
= (char *) ctime (t
);
2844 return (str
? str
: "Sun Jan 01 00:00:00 1970");
2847 /* Emulate sleep...we could have done this with a define, but that
2848 would necessitate including windows.h in the files that used it.
2849 This is much easier. */
2851 sys_sleep (int seconds
)
2853 Sleep (seconds
* 1000);
2856 /* Internal MSVC functions for low-level descriptor munging */
2857 extern int __cdecl
_set_osfhnd (int fd
, long h
);
2858 extern int __cdecl
_free_osfhnd (int fd
);
2860 /* parallel array of private info on file handles */
2861 filedesc fd_info
[ MAXDESC
];
2863 typedef struct volume_info_data
{
2864 struct volume_info_data
* next
;
2866 /* time when info was obtained */
2869 /* actual volume info */
2878 /* Global referenced by various functions. */
2879 static volume_info_data volume_info
;
2881 /* Vector to indicate which drives are local and fixed (for which cached
2882 data never expires). */
2883 static BOOL fixed_drives
[26];
2885 /* Consider cached volume information to be stale if older than 10s,
2886 at least for non-local drives. Info for fixed drives is never stale. */
2887 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
2888 #define VOLINFO_STILL_VALID( root_dir, info ) \
2889 ( ( isalpha (root_dir[0]) && \
2890 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
2891 || GetTickCount () - info->timestamp < 10000 )
2893 /* Cache support functions. */
2895 /* Simple linked list with linear search is sufficient. */
2896 static volume_info_data
*volume_cache
= NULL
;
2898 static volume_info_data
*
2899 lookup_volume_info (char * root_dir
)
2901 volume_info_data
* info
;
2903 for (info
= volume_cache
; info
; info
= info
->next
)
2904 if (xstrcasecmp (info
->root_dir
, root_dir
) == 0)
2910 add_volume_info (char * root_dir
, volume_info_data
* info
)
2912 info
->root_dir
= xstrdup (root_dir
);
2913 unixtodos_filename (info
->root_dir
);
2914 info
->next
= volume_cache
;
2915 volume_cache
= info
;
2919 /* Wrapper for GetVolumeInformation, which uses caching to avoid
2920 performance penalty (~2ms on 486 for local drives, 7.5ms for local
2921 cdrom drive, ~5-10ms or more for remote drives on LAN). */
2922 static volume_info_data
*
2923 GetCachedVolumeInformation (char * root_dir
)
2925 volume_info_data
* info
;
2926 char default_root
[ MAX_UTF8_PATH
];
2927 char name
[MAX_PATH
+1];
2928 char type
[MAX_PATH
+1];
2930 /* NULL for root_dir means use root from current directory. */
2931 if (root_dir
== NULL
)
2933 if (w32_unicode_filenames
)
2935 wchar_t curdirw
[MAX_PATH
];
2937 if (GetCurrentDirectoryW (MAX_PATH
, curdirw
) == 0)
2939 filename_from_utf16 (curdirw
, default_root
);
2943 char curdira
[MAX_PATH
];
2945 if (GetCurrentDirectoryA (MAX_PATH
, curdira
) == 0)
2947 filename_from_ansi (curdira
, default_root
);
2949 parse_root (default_root
, (const char **)&root_dir
);
2951 root_dir
= default_root
;
2954 /* Local fixed drives can be cached permanently. Removable drives
2955 cannot be cached permanently, since the volume name and serial
2956 number (if nothing else) can change. Remote drives should be
2957 treated as if they are removable, since there is no sure way to
2958 tell whether they are or not. Also, the UNC association of drive
2959 letters mapped to remote volumes can be changed at any time (even
2960 by other processes) without notice.
2962 As a compromise, so we can benefit from caching info for remote
2963 volumes, we use a simple expiry mechanism to invalidate cache
2964 entries that are more than ten seconds old. */
2967 /* No point doing this, because WNetGetConnection is even slower than
2968 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
2969 GetDriveType is about the only call of this type which does not
2970 involve network access, and so is extremely quick). */
2972 /* Map drive letter to UNC if remote. */
2973 if (isalpha (root_dir
[0]) && !fixed
[DRIVE_INDEX (root_dir
[0])])
2975 char remote_name
[ 256 ];
2976 char drive
[3] = { root_dir
[0], ':' };
2978 if (WNetGetConnection (drive
, remote_name
, sizeof (remote_name
))
2980 /* do something */ ;
2984 info
= lookup_volume_info (root_dir
);
2986 if (info
== NULL
|| ! VOLINFO_STILL_VALID (root_dir
, info
))
2992 /* Info is not cached, or is stale. */
2993 if (w32_unicode_filenames
)
2995 wchar_t root_w
[MAX_PATH
];
2996 wchar_t name_w
[MAX_PATH
+1];
2997 wchar_t type_w
[MAX_PATH
+1];
2999 filename_to_utf16 (root_dir
, root_w
);
3000 if (!GetVolumeInformationW (root_w
,
3001 name_w
, sizeof (name_w
),
3005 type_w
, sizeof (type_w
)))
3007 /* Hmm... not really 100% correct, as these 2 are not file
3009 filename_from_utf16 (name_w
, name
);
3010 filename_from_utf16 (type_w
, type
);
3014 char root_a
[MAX_PATH
];
3015 char name_a
[MAX_PATH
+1];
3016 char type_a
[MAX_PATH
+1];
3018 filename_to_ansi (root_dir
, root_a
);
3019 if (!GetVolumeInformationA (root_a
,
3020 name_a
, sizeof (name_a
),
3024 type_a
, sizeof (type_a
)))
3026 filename_from_ansi (name_a
, name
);
3027 filename_from_ansi (type_a
, type
);
3030 /* Cache the volume information for future use, overwriting existing
3031 entry if present. */
3034 info
= xmalloc (sizeof (volume_info_data
));
3035 add_volume_info (root_dir
, info
);
3043 info
->name
= xstrdup (name
);
3044 unixtodos_filename (info
->name
);
3045 info
->serialnum
= serialnum
;
3046 info
->maxcomp
= maxcomp
;
3047 info
->flags
= flags
;
3048 info
->type
= xstrdup (type
);
3049 info
->timestamp
= GetTickCount ();
3055 /* Get information on the volume where NAME is held; set path pointer to
3056 start of pathname in NAME (past UNC header\volume header if present),
3057 if pPath is non-NULL.
3059 Note: if NAME includes symlinks, the information is for the volume
3060 of the symlink, not of its target. That's because, even though
3061 GetVolumeInformation returns information about the symlink target
3062 of its argument, we only pass the root directory to
3063 GetVolumeInformation, not the full NAME. */
3065 get_volume_info (const char * name
, const char ** pPath
)
3067 char temp
[MAX_UTF8_PATH
];
3068 char *rootname
= NULL
; /* default to current volume */
3069 volume_info_data
* info
;
3070 int root_len
= parse_root (name
, pPath
);
3075 /* Copy the root name of the volume, if given. */
3078 strncpy (temp
, name
, root_len
);
3079 temp
[root_len
] = '\0';
3080 unixtodos_filename (temp
);
3084 info
= GetCachedVolumeInformation (rootname
);
3087 /* Set global referenced by other functions. */
3088 volume_info
= *info
;
3094 /* Determine if volume is FAT format (ie. only supports short 8.3
3095 names); also set path pointer to start of pathname in name, if
3096 pPath is non-NULL. */
3098 is_fat_volume (const char * name
, const char ** pPath
)
3100 if (get_volume_info (name
, pPath
))
3101 return (volume_info
.maxcomp
== 12);
3105 /* Convert all slashes in a filename to backslashes, and map filename
3106 to a valid 8.3 name if necessary. The result is a pointer to a
3107 static buffer, so CAVEAT EMPTOR! */
3109 map_w32_filename (const char * name
, const char ** pPath
)
3111 static char shortname
[MAX_UTF8_PATH
];
3112 char * str
= shortname
;
3115 const char * save_name
= name
;
3117 if (strlen (name
) >= sizeof (shortname
))
3119 /* Return a filename which will cause callers to fail. */
3120 strcpy (shortname
, "?");
3124 if (is_fat_volume (name
, (const char **)&path
)) /* truncate to 8.3 */
3126 register int left
= 8; /* maximum number of chars in part */
3127 register int extn
= 0; /* extension added? */
3128 register int dots
= 2; /* maximum number of dots allowed */
3131 *str
++ = *name
++; /* skip past UNC header */
3133 while ((c
= *name
++))
3140 *str
++ = (c
== ':' ? ':' : '\\');
3141 extn
= 0; /* reset extension flags */
3142 dots
= 2; /* max 2 dots */
3143 left
= 8; /* max length 8 for main part */
3148 /* Convert path components of the form .xxx to _xxx,
3149 but leave . and .. as they are. This allows .emacs
3150 to be read as _emacs, for example. */
3154 IS_DIRECTORY_SEP (*name
))
3169 extn
= 1; /* we've got an extension */
3170 left
= 3; /* 3 chars in extension */
3174 /* any embedded dots after the first are converted to _ */
3179 case '#': /* don't lose these, they're important */
3181 str
[-1] = c
; /* replace last character of part */
3184 if ( left
&& 'A' <= c
&& c
<= 'Z' )
3186 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
3188 dots
= 0; /* started a path component */
3197 strcpy (shortname
, name
);
3198 unixtodos_filename (shortname
);
3202 *pPath
= shortname
+ (path
- save_name
);
3208 is_exec (const char * name
)
3210 char * p
= strrchr (name
, '.');
3213 && (xstrcasecmp (p
, ".exe") == 0 ||
3214 xstrcasecmp (p
, ".com") == 0 ||
3215 xstrcasecmp (p
, ".bat") == 0 ||
3216 xstrcasecmp (p
, ".cmd") == 0));
3219 /* Emulate the Unix directory procedures opendir, closedir, and
3220 readdir. We rename them to sys_* names because some versions of
3221 MinGW startup code call opendir and readdir to glob wildcards, and
3222 the code that calls them doesn't grok UTF-8 encoded file names we
3223 produce in dirent->d_name[]. */
3225 struct dirent dir_static
; /* simulated directory contents */
3226 static HANDLE dir_find_handle
= INVALID_HANDLE_VALUE
;
3227 static int dir_is_fat
;
3228 static char dir_pathname
[MAX_UTF8_PATH
];
3229 static WIN32_FIND_DATAW dir_find_data_w
;
3230 static WIN32_FIND_DATAA dir_find_data_a
;
3231 #define DIR_FIND_DATA_W 1
3232 #define DIR_FIND_DATA_A 2
3233 static int last_dir_find_data
= -1;
3235 /* Support shares on a network resource as subdirectories of a read-only
3237 static HANDLE wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3238 static HANDLE
open_unc_volume (const char *);
3239 static void *read_unc_volume (HANDLE
, wchar_t *, char *, int);
3240 static void close_unc_volume (HANDLE
);
3243 sys_opendir (const char *filename
)
3247 /* Opening is done by FindFirstFile. However, a read is inherent to
3248 this operation, so we defer the open until read time. */
3250 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3252 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3255 /* Note: We don't support traversal of UNC volumes via symlinks.
3256 Doing so would mean punishing 99.99% of use cases by resolving
3257 all the possible symlinks in FILENAME, recursively. */
3258 if (is_unc_volume (filename
))
3260 wnet_enum_handle
= open_unc_volume (filename
);
3261 if (wnet_enum_handle
== INVALID_HANDLE_VALUE
)
3265 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
3272 strncpy (dir_pathname
, map_w32_filename (filename
, NULL
), MAX_UTF8_PATH
- 1);
3273 dir_pathname
[MAX_UTF8_PATH
- 1] = '\0';
3274 /* Note: We don't support symlinks to file names on FAT volumes.
3275 Doing so would mean punishing 99.99% of use cases by resolving
3276 all the possible symlinks in FILENAME, recursively. */
3277 dir_is_fat
= is_fat_volume (filename
, NULL
);
3283 sys_closedir (DIR *dirp
)
3285 /* If we have a find-handle open, close it. */
3286 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
3288 FindClose (dir_find_handle
);
3289 dir_find_handle
= INVALID_HANDLE_VALUE
;
3291 else if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3293 close_unc_volume (wnet_enum_handle
);
3294 wnet_enum_handle
= INVALID_HANDLE_VALUE
;
3296 xfree ((char *) dirp
);
3300 sys_readdir (DIR *dirp
)
3302 int downcase
= !NILP (Vw32_downcase_file_names
);
3304 if (wnet_enum_handle
!= INVALID_HANDLE_VALUE
)
3306 if (!read_unc_volume (wnet_enum_handle
,
3307 dir_find_data_w
.cFileName
,
3308 dir_find_data_a
.cFileName
,
3312 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
3313 else if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3315 char filename
[MAX_UTF8_PATH
+ 2];
3318 strcpy (filename
, dir_pathname
);
3319 ln
= strlen (filename
) - 1;
3320 if (!IS_DIRECTORY_SEP (filename
[ln
]))
3321 strcat (filename
, "\\");
3322 strcat (filename
, "*");
3324 /* Note: No need to resolve symlinks in FILENAME, because
3325 FindFirst opens the directory that is the target of a
3327 if (w32_unicode_filenames
)
3329 wchar_t fnw
[MAX_PATH
];
3331 filename_to_utf16 (filename
, fnw
);
3332 dir_find_handle
= FindFirstFileW (fnw
, &dir_find_data_w
);
3338 filename_to_ansi (filename
, fna
);
3339 /* If FILENAME is not representable by the current ANSI
3340 codepage, we don't want FindFirstFileA to interpret the
3341 '?' characters as a wildcard. */
3342 if (_mbspbrk (fna
, "?"))
3343 dir_find_handle
= INVALID_HANDLE_VALUE
;
3345 dir_find_handle
= FindFirstFileA (fna
, &dir_find_data_a
);
3348 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
3351 else if (w32_unicode_filenames
)
3353 if (!FindNextFileW (dir_find_handle
, &dir_find_data_w
))
3358 if (!FindNextFileA (dir_find_handle
, &dir_find_data_a
))
3362 /* Emacs never uses this value, so don't bother making it match
3363 value returned by stat(). */
3364 dir_static
.d_ino
= 1;
3366 if (w32_unicode_filenames
)
3368 if (downcase
|| dir_is_fat
)
3370 wchar_t tem
[MAX_PATH
];
3372 wcscpy (tem
, dir_find_data_w
.cFileName
);
3374 filename_from_utf16 (tem
, dir_static
.d_name
);
3377 filename_from_utf16 (dir_find_data_w
.cFileName
, dir_static
.d_name
);
3378 last_dir_find_data
= DIR_FIND_DATA_W
;
3384 /* If the file name in cFileName[] includes `?' characters, it
3385 means the original file name used characters that cannot be
3386 represented by the current ANSI codepage. To avoid total
3387 lossage, retrieve the short 8+3 alias of the long file
3389 if (_mbspbrk (dir_find_data_a
.cFileName
, "?"))
3391 strcpy (tem
, dir_find_data_a
.cAlternateFileName
);
3392 /* 8+3 aliases are returned in all caps, which could break
3393 various alists that look at filenames' extensions. */
3396 else if (downcase
|| dir_is_fat
)
3397 strcpy (tem
, dir_find_data_a
.cFileName
);
3399 filename_from_ansi (dir_find_data_a
.cFileName
, dir_static
.d_name
);
3400 if (downcase
|| dir_is_fat
)
3403 filename_from_ansi (tem
, dir_static
.d_name
);
3405 last_dir_find_data
= DIR_FIND_DATA_A
;
3408 dir_static
.d_namlen
= strlen (dir_static
.d_name
);
3409 dir_static
.d_reclen
= sizeof (struct dirent
) - MAX_UTF8_PATH
+ 3 +
3410 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
3416 open_unc_volume (const char *path
)
3418 const char *fn
= map_w32_filename (path
, NULL
);
3422 if (w32_unicode_filenames
)
3425 wchar_t fnw
[MAX_PATH
];
3427 nrw
.dwScope
= RESOURCE_GLOBALNET
;
3428 nrw
.dwType
= RESOURCETYPE_DISK
;
3429 nrw
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3430 nrw
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3431 nrw
.lpLocalName
= NULL
;
3432 filename_to_utf16 (fn
, fnw
);
3433 nrw
.lpRemoteName
= fnw
;
3434 nrw
.lpComment
= NULL
;
3435 nrw
.lpProvider
= NULL
;
3437 result
= WNetOpenEnumW (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3438 RESOURCEUSAGE_CONNECTABLE
, &nrw
, &henum
);
3445 nra
.dwScope
= RESOURCE_GLOBALNET
;
3446 nra
.dwType
= RESOURCETYPE_DISK
;
3447 nra
.dwDisplayType
= RESOURCEDISPLAYTYPE_SERVER
;
3448 nra
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3449 nra
.lpLocalName
= NULL
;
3450 filename_to_ansi (fn
, fna
);
3451 nra
.lpRemoteName
= fna
;
3452 nra
.lpComment
= NULL
;
3453 nra
.lpProvider
= NULL
;
3455 result
= WNetOpenEnumA (RESOURCE_GLOBALNET
, RESOURCETYPE_DISK
,
3456 RESOURCEUSAGE_CONNECTABLE
, &nra
, &henum
);
3458 if (result
== NO_ERROR
)
3461 return INVALID_HANDLE_VALUE
;
3465 read_unc_volume (HANDLE henum
, wchar_t *fname_w
, char *fname_a
, int size
)
3470 DWORD bufsize
= 512;
3474 if (w32_unicode_filenames
)
3479 buffer
= alloca (bufsize
);
3480 result
= WNetEnumResourceW (henum
, &count
, buffer
, &bufsize
);
3481 if (result
!= NO_ERROR
)
3483 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3484 ptrw
= ((LPNETRESOURCEW
) buffer
)->lpRemoteName
;
3486 while (*ptrw
&& *ptrw
!= L
'/' && *ptrw
!= L
'\\') ptrw
++;
3488 wcsncpy (fname_w
, ptrw
, size
);
3493 int dbcs_p
= max_filename_mbslen () > 1;
3496 buffer
= alloca (bufsize
);
3497 result
= WNetEnumResourceA (henum
, &count
, buffer
, &bufsize
);
3498 if (result
!= NO_ERROR
)
3500 ptra
= ((LPNETRESOURCEA
) buffer
)->lpRemoteName
;
3503 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
)) ptra
++;
3506 while (*ptra
&& !IS_DIRECTORY_SEP (*ptra
))
3507 ptra
= CharNextExA (file_name_codepage
, ptra
, 0);
3510 strncpy (fname_a
, ptra
, size
);
3518 close_unc_volume (HANDLE henum
)
3520 if (henum
!= INVALID_HANDLE_VALUE
)
3521 WNetCloseEnum (henum
);
3525 unc_volume_file_attributes (const char *path
)
3530 henum
= open_unc_volume (path
);
3531 if (henum
== INVALID_HANDLE_VALUE
)
3534 attrs
= FILE_ATTRIBUTE_READONLY
| FILE_ATTRIBUTE_DIRECTORY
;
3536 close_unc_volume (henum
);
3541 /* Ensure a network connection is authenticated. */
3543 logon_network_drive (const char *path
)
3545 char share
[MAX_UTF8_PATH
];
3552 if (IS_DIRECTORY_SEP (path
[0]) && IS_DIRECTORY_SEP (path
[1]))
3553 drvtype
= DRIVE_REMOTE
;
3554 else if (path
[0] == '\0' || path
[1] != ':')
3555 drvtype
= GetDriveType (NULL
);
3562 drvtype
= GetDriveType (drive
);
3565 /* Only logon to networked drives. */
3566 if (drvtype
!= DRIVE_REMOTE
)
3570 strncpy (share
, path
, MAX_UTF8_PATH
);
3571 /* Truncate to just server and share name. */
3572 for (p
= share
+ 2; *p
&& p
< share
+ MAX_UTF8_PATH
; p
++)
3574 if (IS_DIRECTORY_SEP (*p
) && ++n_slashes
> 3)
3581 if (w32_unicode_filenames
)
3583 NETRESOURCEW resourcew
;
3584 wchar_t share_w
[MAX_PATH
];
3586 resourcew
.dwScope
= RESOURCE_GLOBALNET
;
3587 resourcew
.dwType
= RESOURCETYPE_DISK
;
3588 resourcew
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3589 resourcew
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3590 resourcew
.lpLocalName
= NULL
;
3591 filename_to_utf16 (share
, share_w
);
3592 resourcew
.lpRemoteName
= share_w
;
3593 resourcew
.lpProvider
= NULL
;
3595 val
= WNetAddConnection2W (&resourcew
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3599 NETRESOURCEA resourcea
;
3600 char share_a
[MAX_PATH
];
3602 resourcea
.dwScope
= RESOURCE_GLOBALNET
;
3603 resourcea
.dwType
= RESOURCETYPE_DISK
;
3604 resourcea
.dwDisplayType
= RESOURCEDISPLAYTYPE_SHARE
;
3605 resourcea
.dwUsage
= RESOURCEUSAGE_CONTAINER
;
3606 resourcea
.lpLocalName
= NULL
;
3607 filename_to_ansi (share
, share_a
);
3608 resourcea
.lpRemoteName
= share_a
;
3609 resourcea
.lpProvider
= NULL
;
3611 val
= WNetAddConnection2A (&resourcea
, NULL
, NULL
, CONNECT_INTERACTIVE
);
3617 case ERROR_ALREADY_ASSIGNED
:
3619 case ERROR_ACCESS_DENIED
:
3620 case ERROR_LOGON_FAILURE
:
3626 case ERROR_BAD_NET_NAME
:
3627 case ERROR_NO_NET_OR_BAD_PATH
:
3628 case ERROR_NO_NETWORK
:
3629 case ERROR_CANCELLED
:
3636 /* Emulate faccessat(2). */
3638 faccessat (int dirfd
, const char * path
, int mode
, int flags
)
3642 if (dirfd
!= AT_FDCWD
3643 && !(IS_DIRECTORY_SEP (path
[0])
3644 || IS_DEVICE_SEP (path
[1])))
3650 /* MSVCRT implementation of 'access' doesn't recognize D_OK, and its
3651 newer versions blow up when passed D_OK. */
3652 path
= map_w32_filename (path
, NULL
);
3653 /* If the last element of PATH is a symlink, we need to resolve it
3654 to get the attributes of its target file. Note: any symlinks in
3655 PATH elements other than the last one are transparently resolved
3656 by GetFileAttributes below. */
3657 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0
3658 && (flags
& AT_SYMLINK_NOFOLLOW
) == 0)
3659 path
= chase_symlinks (path
);
3661 if (w32_unicode_filenames
)
3663 wchar_t path_w
[MAX_PATH
];
3665 filename_to_utf16 (path
, path_w
);
3666 attributes
= GetFileAttributesW (path_w
);
3670 char path_a
[MAX_PATH
];
3672 filename_to_ansi (path
, path_a
);
3673 attributes
= GetFileAttributesA (path_a
);
3676 if (attributes
== -1)
3678 DWORD w32err
= GetLastError ();
3682 case ERROR_INVALID_NAME
:
3683 case ERROR_BAD_PATHNAME
:
3684 if (is_unc_volume (path
))
3686 attributes
= unc_volume_file_attributes (path
);
3687 if (attributes
== -1)
3695 case ERROR_FILE_NOT_FOUND
:
3696 case ERROR_BAD_NETPATH
:
3705 if ((mode
& X_OK
) != 0
3706 && !(is_exec (path
) || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3711 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3716 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3724 /* A version of 'access' to be used locally with file names in
3725 locale-specific encoding. Does not resolve symlinks and does not
3726 support file names on FAT12 and FAT16 volumes, but that's OK, since
3727 we only invoke this function for files inside the Emacs source or
3728 installation tree, on directories (so any symlinks should have the
3729 directory bit set), and on short file names such as "C:/.emacs". */
3731 sys_access (const char *fname
, int mode
)
3733 char fname_copy
[MAX_PATH
], *p
;
3736 strcpy (fname_copy
, fname
);
3737 /* Do the equivalent of unixtodos_filename. */
3738 for (p
= fname_copy
; *p
; p
= CharNext (p
))
3742 if ((attributes
= GetFileAttributesA (fname_copy
)) == -1)
3744 DWORD w32err
= GetLastError ();
3748 case ERROR_INVALID_NAME
:
3749 case ERROR_BAD_PATHNAME
:
3750 case ERROR_FILE_NOT_FOUND
:
3751 case ERROR_BAD_NETPATH
:
3760 if ((mode
& X_OK
) != 0
3761 && !(is_exec (fname_copy
)
3762 || (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0))
3767 if ((mode
& W_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_READONLY
) != 0)
3772 if ((mode
& D_OK
) != 0 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
3780 /* Shadow some MSVC runtime functions to map requests for long filenames
3781 to reasonable short names if necessary. This was originally added to
3782 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
3786 sys_chdir (const char * path
)
3788 path
= map_w32_filename (path
, NULL
);
3789 if (w32_unicode_filenames
)
3791 wchar_t newdir_w
[MAX_PATH
];
3793 if (filename_to_utf16 (path
, newdir_w
) == 0)
3794 return _wchdir (newdir_w
);
3799 char newdir_a
[MAX_PATH
];
3801 if (filename_to_ansi (path
, newdir_a
) == 0)
3802 return _chdir (newdir_a
);
3808 sys_chmod (const char * path
, int mode
)
3810 path
= chase_symlinks (map_w32_filename (path
, NULL
));
3811 if (w32_unicode_filenames
)
3813 wchar_t path_w
[MAX_PATH
];
3815 filename_to_utf16 (path
, path_w
);
3816 return _wchmod (path_w
, mode
);
3820 char path_a
[MAX_PATH
];
3822 filename_to_ansi (path
, path_a
);
3823 return _chmod (path_a
, mode
);
3828 sys_creat (const char * path
, int mode
)
3830 path
= map_w32_filename (path
, NULL
);
3831 if (w32_unicode_filenames
)
3833 wchar_t path_w
[MAX_PATH
];
3835 filename_to_utf16 (path
, path_w
);
3836 return _wcreat (path_w
, mode
);
3840 char path_a
[MAX_PATH
];
3842 filename_to_ansi (path
, path_a
);
3843 return _creat (path_a
, mode
);
3848 sys_fopen (const char * path
, const char * mode
)
3852 const char * mode_save
= mode
;
3854 /* Force all file handles to be non-inheritable. This is necessary to
3855 ensure child processes don't unwittingly inherit handles that might
3856 prevent future file access. */
3860 else if (mode
[0] == 'w' || mode
[0] == 'a')
3861 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
3865 /* Only do simplistic option parsing. */
3869 oflag
&= ~(O_RDONLY
| O_WRONLY
);
3872 else if (mode
[0] == 'b')
3877 else if (mode
[0] == 't')
3884 path
= map_w32_filename (path
, NULL
);
3885 if (w32_unicode_filenames
)
3887 wchar_t path_w
[MAX_PATH
];
3889 filename_to_utf16 (path
, path_w
);
3890 fd
= _wopen (path_w
, oflag
| _O_NOINHERIT
, 0644);
3894 char path_a
[MAX_PATH
];
3896 filename_to_ansi (path
, path_a
);
3897 fd
= _open (path_a
, oflag
| _O_NOINHERIT
, 0644);
3902 return _fdopen (fd
, mode_save
);
3905 /* This only works on NTFS volumes, but is useful to have. */
3907 sys_link (const char * old
, const char * new)
3911 char oldname
[MAX_UTF8_PATH
], newname
[MAX_UTF8_PATH
];
3912 wchar_t oldname_w
[MAX_PATH
];
3913 char oldname_a
[MAX_PATH
];
3915 if (old
== NULL
|| new == NULL
)
3921 strcpy (oldname
, map_w32_filename (old
, NULL
));
3922 strcpy (newname
, map_w32_filename (new, NULL
));
3924 if (w32_unicode_filenames
)
3926 filename_to_utf16 (oldname
, oldname_w
);
3927 fileh
= CreateFileW (oldname_w
, 0, 0, NULL
, OPEN_EXISTING
,
3928 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3932 filename_to_ansi (oldname
, oldname_a
);
3933 fileh
= CreateFileA (oldname_a
, 0, 0, NULL
, OPEN_EXISTING
,
3934 FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
3936 if (fileh
!= INVALID_HANDLE_VALUE
)
3940 /* Confusingly, the "alternate" stream name field does not apply
3941 when restoring a hard link, and instead contains the actual
3942 stream data for the link (ie. the name of the link to create).
3943 The WIN32_STREAM_ID structure before the cStreamName field is
3944 the stream header, which is then immediately followed by the
3948 WIN32_STREAM_ID wid
;
3949 WCHAR wbuffer
[MAX_PATH
]; /* extra space for link name */
3952 /* We used to pass MB_PRECOMPOSED as the 2nd arg here, but MSDN
3953 indicates that flag is unsupported for CP_UTF8, and OTOH says
3954 it is the default anyway. */
3955 wlen
= MultiByteToWideChar (CP_UTF8
, 0, newname
, -1,
3956 data
.wid
.cStreamName
, MAX_PATH
);
3959 LPVOID context
= NULL
;
3962 data
.wid
.dwStreamId
= BACKUP_LINK
;
3963 data
.wid
.dwStreamAttributes
= 0;
3964 data
.wid
.Size
.LowPart
= wlen
* sizeof (WCHAR
);
3965 data
.wid
.Size
.HighPart
= 0;
3966 data
.wid
.dwStreamNameSize
= 0;
3968 if (BackupWrite (fileh
, (LPBYTE
)&data
,
3969 offsetof (WIN32_STREAM_ID
, cStreamName
)
3970 + data
.wid
.Size
.LowPart
,
3971 &wbytes
, FALSE
, FALSE
, &context
)
3972 && BackupWrite (fileh
, NULL
, 0, &wbytes
, TRUE
, FALSE
, &context
))
3979 DWORD err
= GetLastError ();
3984 case ERROR_ACCESS_DENIED
:
3985 /* This is what happens when OLDNAME is a directory,
3986 since Windows doesn't support hard links to
3987 directories. Posix says to set errno to EPERM in
3989 if (w32_unicode_filenames
)
3990 attributes
= GetFileAttributesW (oldname_w
);
3992 attributes
= GetFileAttributesA (oldname_a
);
3993 if (attributes
!= -1
3994 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
) != 0)
3996 else if (attributes
== -1
3997 && is_unc_volume (oldname
)
3998 && unc_volume_file_attributes (oldname
) != -1)
4003 case ERROR_TOO_MANY_LINKS
:
4006 case ERROR_NOT_SAME_DEVICE
:
4016 CloseHandle (fileh
);
4025 sys_mkdir (const char * path
)
4027 path
= map_w32_filename (path
, NULL
);
4029 if (w32_unicode_filenames
)
4031 wchar_t path_w
[MAX_PATH
];
4033 filename_to_utf16 (path
, path_w
);
4034 return _wmkdir (path_w
);
4038 char path_a
[MAX_PATH
];
4040 filename_to_ansi (path
, path_a
);
4041 return _mkdir (path_a
);
4046 sys_open (const char * path
, int oflag
, int mode
)
4048 const char* mpath
= map_w32_filename (path
, NULL
);
4051 if (w32_unicode_filenames
)
4053 wchar_t mpath_w
[MAX_PATH
];
4055 filename_to_utf16 (mpath
, mpath_w
);
4056 /* If possible, try to open file without _O_CREAT, to be able to
4057 write to existing hidden and system files. Force all file
4058 handles to be non-inheritable. */
4059 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4060 res
= _wopen (mpath_w
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4062 res
= _wopen (mpath_w
, oflag
| _O_NOINHERIT
, mode
);
4066 char mpath_a
[MAX_PATH
];
4068 filename_to_ansi (mpath
, mpath_a
);
4069 if ((oflag
& (_O_CREAT
| _O_EXCL
)) != (_O_CREAT
| _O_EXCL
))
4070 res
= _open (mpath_a
, (oflag
& ~_O_CREAT
) | _O_NOINHERIT
, mode
);
4072 res
= _open (mpath_a
, oflag
| _O_NOINHERIT
, mode
);
4078 /* Implementation of mkostemp for MS-Windows, to avoid race conditions
4081 Standard algorithm for generating a temporary file name seems to be
4082 use pid or tid with a letter on the front (in place of the 6 X's)
4083 and cycle through the letters to find a unique name. We extend
4084 that to allow any reasonable character as the first of the 6 X's,
4085 so that the number of simultaneously used temporary files will be
4089 mkostemp (char * template, int flags
)
4093 unsigned uid
= GetCurrentThreadId ();
4094 int save_errno
= errno
;
4095 static char first_char
[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
4098 if (template == NULL
)
4101 p
= template + strlen (template);
4103 /* replace up to the last 5 X's with uid in decimal */
4104 while (--p
>= template && p
[0] == 'X' && --i
>= 0)
4106 p
[0] = '0' + uid
% 10;
4110 if (i
< 0 && p
[0] == 'X')
4115 p
[0] = first_char
[i
];
4116 if ((fd
= sys_open (template,
4117 flags
| _O_CREAT
| _O_EXCL
| _O_RDWR
,
4118 S_IRUSR
| S_IWUSR
)) >= 0
4126 while (++i
< sizeof (first_char
));
4129 /* Template is badly formed or else we can't generate a unique name. */
4134 fchmod (int fd
, mode_t mode
)
4140 sys_rename_replace (const char *oldname
, const char *newname
, BOOL force
)
4143 char temp
[MAX_UTF8_PATH
], temp_a
[MAX_PATH
];;
4146 bool have_temp_a
= false;
4148 /* MoveFile on Windows 95 doesn't correctly change the short file name
4149 alias in a number of circumstances (it is not easy to predict when
4150 just by looking at oldname and newname, unfortunately). In these
4151 cases, renaming through a temporary name avoids the problem.
4153 A second problem on Windows 95 is that renaming through a temp name when
4154 newname is uppercase fails (the final long name ends up in
4155 lowercase, although the short alias might be uppercase) UNLESS the
4156 long temp name is not 8.3.
4158 So, on Windows 95 we always rename through a temp name, and we make sure
4159 the temp name has a long extension to ensure correct renaming. */
4161 strcpy (temp
, map_w32_filename (oldname
, NULL
));
4163 /* volume_info is set indirectly by map_w32_filename. */
4164 oldname_dev
= volume_info
.serialnum
;
4166 if (os_subtype
== OS_9X
)
4171 char oldname_a
[MAX_PATH
];
4173 oldname
= map_w32_filename (oldname
, NULL
);
4174 filename_to_ansi (oldname
, oldname_a
);
4175 filename_to_ansi (temp
, temp_a
);
4176 if ((o
= strrchr (oldname_a
, '\\')))
4179 o
= (char *) oldname_a
;
4181 if ((p
= strrchr (temp_a
, '\\')))
4188 /* Force temp name to require a manufactured 8.3 alias - this
4189 seems to make the second rename work properly. */
4190 sprintf (p
, "_.%s.%u", o
, i
);
4192 result
= rename (oldname_a
, temp_a
);
4194 /* This loop must surely terminate! */
4195 while (result
< 0 && errno
== EEXIST
);
4201 /* If FORCE, emulate Unix behavior - newname is deleted if it already exists
4202 (at least if it is a file; don't do this for directories).
4204 Since we mustn't do this if we are just changing the case of the
4205 file name (we would end up deleting the file we are trying to
4206 rename!), we let rename detect if the destination file already
4207 exists - that way we avoid the possible pitfalls of trying to
4208 determine ourselves whether two names really refer to the same
4209 file, which is not always possible in the general case. (Consider
4210 all the permutations of shared or subst'd drives, etc.) */
4212 newname
= map_w32_filename (newname
, NULL
);
4214 /* volume_info is set indirectly by map_w32_filename. */
4215 newname_dev
= volume_info
.serialnum
;
4217 if (w32_unicode_filenames
)
4219 wchar_t temp_w
[MAX_PATH
], newname_w
[MAX_PATH
];
4221 filename_to_utf16 (temp
, temp_w
);
4222 filename_to_utf16 (newname
, newname_w
);
4223 result
= _wrename (temp_w
, newname_w
);
4224 if (result
< 0 && force
)
4226 DWORD w32err
= GetLastError ();
4229 && newname_dev
!= oldname_dev
)
4231 /* The implementation of `rename' on Windows does not return
4232 errno = EXDEV when you are moving a directory to a
4233 different storage device (ex. logical disk). It returns
4234 EACCES instead. So here we handle such situations and
4238 if ((attributes
= GetFileAttributesW (temp_w
)) != -1
4239 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4242 else if (errno
== EEXIST
)
4244 if (_wchmod (newname_w
, 0666) != 0)
4246 if (_wunlink (newname_w
) != 0)
4248 result
= _wrename (temp_w
, newname_w
);
4250 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4251 && is_symlink (temp
))
4253 /* This is Windows prohibiting the user from creating a
4254 symlink in another place, since that requires
4262 char newname_a
[MAX_PATH
];
4265 filename_to_ansi (temp
, temp_a
);
4266 filename_to_ansi (newname
, newname_a
);
4267 result
= rename (temp_a
, newname_a
);
4268 if (result
< 0 && force
)
4270 DWORD w32err
= GetLastError ();
4273 && newname_dev
!= oldname_dev
)
4277 if ((attributes
= GetFileAttributesA (temp_a
)) != -1
4278 && (attributes
& FILE_ATTRIBUTE_DIRECTORY
))
4281 else if (errno
== EEXIST
)
4283 if (_chmod (newname_a
, 0666) != 0)
4285 if (_unlink (newname_a
) != 0)
4287 result
= rename (temp_a
, newname_a
);
4289 else if (w32err
== ERROR_PRIVILEGE_NOT_HELD
4290 && is_symlink (temp
))
4299 sys_rename (char const *old
, char const *new)
4301 return sys_rename_replace (old
, new, TRUE
);
4305 sys_rmdir (const char * path
)
4307 path
= map_w32_filename (path
, NULL
);
4309 if (w32_unicode_filenames
)
4311 wchar_t path_w
[MAX_PATH
];
4313 filename_to_utf16 (path
, path_w
);
4314 return _wrmdir (path_w
);
4318 char path_a
[MAX_PATH
];
4320 filename_to_ansi (path
, path_a
);
4321 return _rmdir (path_a
);
4326 sys_unlink (const char * path
)
4328 path
= map_w32_filename (path
, NULL
);
4330 if (w32_unicode_filenames
)
4332 wchar_t path_w
[MAX_PATH
];
4334 filename_to_utf16 (path
, path_w
);
4335 /* On Unix, unlink works without write permission. */
4336 _wchmod (path_w
, 0666);
4337 return _wunlink (path_w
);
4341 char path_a
[MAX_PATH
];
4343 filename_to_ansi (path
, path_a
);
4344 _chmod (path_a
, 0666);
4345 return _unlink (path_a
);
4349 static FILETIME utc_base_ft
;
4350 static ULONGLONG utc_base
; /* In 100ns units */
4351 static int init
= 0;
4353 #define FILETIME_TO_U64(result, ft) \
4355 ULARGE_INTEGER uiTemp; \
4356 uiTemp.LowPart = (ft).dwLowDateTime; \
4357 uiTemp.HighPart = (ft).dwHighDateTime; \
4358 result = uiTemp.QuadPart; \
4362 initialize_utc_base (void)
4364 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
4373 st
.wMilliseconds
= 0;
4375 SystemTimeToFileTime (&st
, &utc_base_ft
);
4376 FILETIME_TO_U64 (utc_base
, utc_base_ft
);
4380 convert_time (FILETIME ft
)
4386 initialize_utc_base ();
4390 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
4393 FILETIME_TO_U64 (tmp
, ft
);
4394 return (time_t) ((tmp
- utc_base
) / 10000000L);
4398 convert_from_time_t (time_t time
, FILETIME
* pft
)
4404 initialize_utc_base ();
4408 /* time in 100ns units since 1-Jan-1601 */
4409 tmp
.QuadPart
= (ULONGLONG
) time
* 10000000L + utc_base
;
4410 pft
->dwHighDateTime
= tmp
.HighPart
;
4411 pft
->dwLowDateTime
= tmp
.LowPart
;
4414 static PSECURITY_DESCRIPTOR
4415 get_file_security_desc_by_handle (HANDLE h
)
4417 PSECURITY_DESCRIPTOR psd
= NULL
;
4419 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4420 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4422 err
= get_security_info (h
, SE_FILE_OBJECT
, si
,
4423 NULL
, NULL
, NULL
, NULL
, &psd
);
4424 if (err
!= ERROR_SUCCESS
)
4430 static PSECURITY_DESCRIPTOR
4431 get_file_security_desc_by_name (const char *fname
)
4433 PSECURITY_DESCRIPTOR psd
= NULL
;
4435 SECURITY_INFORMATION si
= OWNER_SECURITY_INFORMATION
4436 | GROUP_SECURITY_INFORMATION
/* | DACL_SECURITY_INFORMATION */ ;
4438 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
))
4440 err
= GetLastError ();
4441 if (err
!= ERROR_INSUFFICIENT_BUFFER
)
4445 psd
= xmalloc (sd_len
);
4446 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
4458 unsigned n_subauthorities
;
4460 /* Use the last sub-authority value of the RID, the relative
4461 portion of the SID, as user/group ID. */
4462 n_subauthorities
= *get_sid_sub_authority_count (sid
);
4463 if (n_subauthorities
< 1)
4464 return 0; /* the "World" RID */
4465 return *get_sid_sub_authority (sid
, n_subauthorities
- 1);
4468 /* Caching SID and account values for faster lokup. */
4472 struct w32_id
*next
;
4474 unsigned char sid
[FLEXIBLE_ARRAY_MEMBER
];
4477 static struct w32_id
*w32_idlist
;
4480 w32_cached_id (PSID sid
, unsigned *id
, char *name
)
4482 struct w32_id
*tail
, *found
;
4484 for (found
= NULL
, tail
= w32_idlist
; tail
; tail
= tail
->next
)
4486 if (equal_sid ((PSID
)tail
->sid
, sid
))
4495 strcpy (name
, found
->name
);
4503 w32_add_to_cache (PSID sid
, unsigned id
, char *name
)
4506 struct w32_id
*new_entry
;
4508 /* We don't want to leave behind stale cache from when Emacs was
4512 sid_len
= get_length_sid (sid
);
4513 new_entry
= xmalloc (offsetof (struct w32_id
, sid
) + sid_len
);
4516 new_entry
->rid
= id
;
4517 strcpy (new_entry
->name
, name
);
4518 copy_sid (sid_len
, (PSID
)new_entry
->sid
, sid
);
4519 new_entry
->next
= w32_idlist
;
4520 w32_idlist
= new_entry
;
4529 get_name_and_id (PSECURITY_DESCRIPTOR psd
, unsigned *id
, char *nm
, int what
)
4533 SID_NAME_USE ignore
;
4535 DWORD name_len
= sizeof (name
);
4537 DWORD domain_len
= sizeof (domain
);
4542 result
= get_security_descriptor_owner (psd
, &sid
, &dflt
);
4543 else if (what
== GID
)
4544 result
= get_security_descriptor_group (psd
, &sid
, &dflt
);
4548 if (!result
|| !is_valid_sid (sid
))
4550 else if (!w32_cached_id (sid
, id
, nm
))
4552 if (!lookup_account_sid (NULL
, sid
, name
, &name_len
,
4553 domain
, &domain_len
, &ignore
)
4554 || name_len
> UNLEN
+1)
4558 *id
= get_rid (sid
);
4560 w32_add_to_cache (sid
, *id
, name
);
4567 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd
, struct stat
*st
)
4569 int dflt_usr
= 0, dflt_grp
= 0;
4578 if (get_name_and_id (psd
, &st
->st_uid
, st
->st_uname
, UID
))
4580 if (get_name_and_id (psd
, &st
->st_gid
, st
->st_gname
, GID
))
4583 /* Consider files to belong to current user/group, if we cannot get
4584 more accurate information. */
4587 st
->st_uid
= dflt_passwd
.pw_uid
;
4588 strcpy (st
->st_uname
, dflt_passwd
.pw_name
);
4592 st
->st_gid
= dflt_passwd
.pw_gid
;
4593 strcpy (st
->st_gname
, dflt_group
.gr_name
);
4597 /* Return non-zero if NAME is a potentially slow filesystem. */
4599 is_slow_fs (const char *name
)
4604 if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
4605 devtype
= DRIVE_REMOTE
; /* assume UNC name is remote */
4606 else if (!(strlen (name
) >= 2 && IS_DEVICE_SEP (name
[1])))
4607 devtype
= GetDriveType (NULL
); /* use root of current drive */
4610 /* GetDriveType needs the root directory of the drive. */
4611 strncpy (drive_root
, name
, 2);
4612 drive_root
[2] = '\\';
4613 drive_root
[3] = '\0';
4614 devtype
= GetDriveType (drive_root
);
4616 return !(devtype
== DRIVE_FIXED
|| devtype
== DRIVE_RAMDISK
);
4619 /* If this is non-zero, the caller wants accurate information about
4620 file's owner and group, which could be expensive to get. dired.c
4621 uses this flag when needed for the job at hand. */
4622 int w32_stat_get_owner_group
;
4624 /* MSVC stat function can't cope with UNC names and has other bugs, so
4625 replace it with our own. This also allows us to calculate consistent
4626 inode values and owner/group without hacks in the main Emacs code,
4627 and support file names encoded in UTF-8. */
4630 stat_worker (const char * path
, struct stat
* buf
, int follow_symlinks
)
4632 char *name
, *save_name
, *r
;
4633 WIN32_FIND_DATAW wfd_w
;
4634 WIN32_FIND_DATAA wfd_a
;
4636 unsigned __int64 fake_inode
= 0;
4639 int rootdir
= FALSE
;
4640 PSECURITY_DESCRIPTOR psd
= NULL
;
4641 int is_a_symlink
= 0;
4642 DWORD file_flags
= FILE_FLAG_BACKUP_SEMANTICS
;
4643 DWORD access_rights
= 0;
4644 DWORD fattrs
= 0, serialnum
= 0, fs_high
= 0, fs_low
= 0, nlinks
= 1;
4645 FILETIME ctime
, atime
, wtime
;
4646 wchar_t name_w
[MAX_PATH
];
4647 char name_a
[MAX_PATH
];
4649 if (path
== NULL
|| buf
== NULL
)
4655 save_name
= name
= (char *) map_w32_filename (path
, &path
);
4656 /* Must be valid filename, no wild cards or other invalid
4658 if (strpbrk (name
, "*?|<>\""))
4664 /* Remove trailing directory separator, unless name is the root
4665 directory of a drive or UNC volume in which case ensure there
4666 is a trailing separator. */
4667 len
= strlen (name
);
4668 name
= strcpy (alloca (len
+ 2), name
);
4670 /* Avoid a somewhat costly call to is_symlink if the filesystem
4671 doesn't support symlinks. */
4672 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
4673 is_a_symlink
= is_symlink (name
);
4675 /* Plan A: Open the file and get all the necessary information via
4676 the resulting handle. This solves several issues in one blow:
4678 . retrieves attributes for the target of a symlink, if needed
4679 . gets attributes of root directories and symlinks pointing to
4680 root directories, thus avoiding the need for special-casing
4681 these and detecting them by examining the file-name format
4682 . retrieves more accurate attributes (e.g., non-zero size for
4683 some directories, esp. directories that are junction points)
4684 . correctly resolves "c:/..", "/.." and similar file names
4685 . avoids run-time penalties for 99% of use cases
4687 Plan A is always tried first, unless the user asked not to (but
4688 if the file is a symlink and we need to follow links, we try Plan
4689 A even if the user asked not to).
4691 If Plan A fails, we go to Plan B (below), where various
4692 potentially expensive techniques must be used to handle "special"
4693 files such as UNC volumes etc. */
4694 if (!(NILP (Vw32_get_true_file_attributes
)
4695 || (EQ (Vw32_get_true_file_attributes
, Qlocal
) && is_slow_fs (name
)))
4696 /* Following symlinks requires getting the info by handle. */
4697 || (is_a_symlink
&& follow_symlinks
))
4699 BY_HANDLE_FILE_INFORMATION info
;
4701 if (is_a_symlink
&& !follow_symlinks
)
4702 file_flags
|= FILE_FLAG_OPEN_REPARSE_POINT
;
4703 /* READ_CONTROL access rights are required to get security info
4704 by handle. But if the OS doesn't support security in the
4705 first place, we don't need to try. */
4706 if (is_windows_9x () != TRUE
)
4707 access_rights
|= READ_CONTROL
;
4709 if (w32_unicode_filenames
)
4711 filename_to_utf16 (name
, name_w
);
4712 fh
= CreateFileW (name_w
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4714 /* If CreateFile fails with READ_CONTROL, try again with
4715 zero as access rights. */
4716 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4717 fh
= CreateFileW (name_w
, 0, 0, NULL
, OPEN_EXISTING
,
4722 filename_to_ansi (name
, name_a
);
4723 fh
= CreateFileA (name_a
, access_rights
, 0, NULL
, OPEN_EXISTING
,
4725 if (fh
== INVALID_HANDLE_VALUE
&& access_rights
)
4726 fh
= CreateFileA (name_a
, 0, 0, NULL
, OPEN_EXISTING
,
4729 if (fh
== INVALID_HANDLE_VALUE
)
4730 goto no_true_file_attributes
;
4732 /* This is more accurate in terms of getting the correct number
4733 of links, but is quite slow (it is noticeable when Emacs is
4734 making a list of file name completions). */
4735 if (GetFileInformationByHandle (fh
, &info
))
4737 nlinks
= info
.nNumberOfLinks
;
4738 /* Might as well use file index to fake inode values, but this
4739 is not guaranteed to be unique unless we keep a handle open
4740 all the time (even then there are situations where it is
4741 not unique). Reputedly, there are at most 48 bits of info
4742 (on NTFS, presumably less on FAT). */
4743 fake_inode
= info
.nFileIndexHigh
;
4745 fake_inode
+= info
.nFileIndexLow
;
4746 serialnum
= info
.dwVolumeSerialNumber
;
4747 fs_high
= info
.nFileSizeHigh
;
4748 fs_low
= info
.nFileSizeLow
;
4749 ctime
= info
.ftCreationTime
;
4750 atime
= info
.ftLastAccessTime
;
4751 wtime
= info
.ftLastWriteTime
;
4752 fattrs
= info
.dwFileAttributes
;
4756 /* We don't go to Plan B here, because it's not clear that
4757 it's a good idea. The only known use case where
4758 CreateFile succeeds, but GetFileInformationByHandle fails
4759 (with ERROR_INVALID_FUNCTION) is for character devices
4760 such as NUL, PRN, etc. For these, switching to Plan B is
4761 a net loss, because we lose the character device
4762 attribute returned by GetFileType below (FindFirstFile
4763 doesn't set that bit in the attributes), and the other
4764 fields don't make sense for character devices anyway.
4765 Emacs doesn't really care for non-file entities in the
4766 context of l?stat, so neither do we. */
4768 /* w32err is assigned so one could put a breakpoint here and
4769 examine its value, when GetFileInformationByHandle
4771 DWORD w32err
= GetLastError ();
4775 case ERROR_FILE_NOT_FOUND
: /* can this ever happen? */
4781 /* Test for a symlink before testing for a directory, since
4782 symlinks to directories have the directory bit set, but we
4783 don't want them to appear as directories. */
4784 if (is_a_symlink
&& !follow_symlinks
)
4785 buf
->st_mode
= S_IFLNK
;
4786 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4787 buf
->st_mode
= S_IFDIR
;
4790 DWORD ftype
= GetFileType (fh
);
4794 case FILE_TYPE_DISK
:
4795 buf
->st_mode
= S_IFREG
;
4797 case FILE_TYPE_PIPE
:
4798 buf
->st_mode
= S_IFIFO
;
4800 case FILE_TYPE_CHAR
:
4801 case FILE_TYPE_UNKNOWN
:
4803 buf
->st_mode
= S_IFCHR
;
4806 /* We produce the fallback owner and group data, based on the
4807 current user that runs Emacs, in the following cases:
4809 . caller didn't request owner and group info
4810 . this is Windows 9X
4811 . getting security by handle failed, and we need to produce
4812 information for the target of a symlink (this is better
4813 than producing a potentially misleading info about the
4816 If getting security by handle fails, and we don't need to
4817 resolve symlinks, we try getting security by name. */
4818 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
4819 get_file_owner_and_group (NULL
, buf
);
4822 psd
= get_file_security_desc_by_handle (fh
);
4825 get_file_owner_and_group (psd
, buf
);
4828 else if (!(is_a_symlink
&& follow_symlinks
))
4830 psd
= get_file_security_desc_by_name (name
);
4831 get_file_owner_and_group (psd
, buf
);
4835 get_file_owner_and_group (NULL
, buf
);
4841 no_true_file_attributes
:
4842 /* Plan B: Either getting a handle on the file failed, or the
4843 caller explicitly asked us to not bother making this
4844 information more accurate.
4846 Implementation note: In Plan B, we never bother to resolve
4847 symlinks, even if we got here because we tried Plan A and
4848 failed. That's because, even if the caller asked for extra
4849 precision by setting Vw32_get_true_file_attributes to t,
4850 resolving symlinks requires acquiring a file handle to the
4851 symlink, which we already know will fail. And if the user
4852 did not ask for extra precision, resolving symlinks will fly
4853 in the face of that request, since the user then wants the
4854 lightweight version of the code. */
4855 rootdir
= (path
>= save_name
+ len
- 1
4856 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
4858 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
4859 r
= IS_DEVICE_SEP (name
[1]) ? &name
[2] : name
;
4860 if (IS_DIRECTORY_SEP (r
[0])
4861 && r
[1] == '.' && r
[2] == '.' && r
[3] == '\0')
4864 /* Note: If NAME is a symlink to the root of a UNC volume
4865 (i.e. "\\SERVER"), we will not detect that here, and we will
4866 return data about the symlink as result of FindFirst below.
4867 This is unfortunate, but that marginal use case does not
4868 justify a call to chase_symlinks which would impose a penalty
4869 on all the other use cases. (We get here for symlinks to
4870 roots of UNC volumes because CreateFile above fails for them,
4871 unlike with symlinks to root directories X:\ of drives.) */
4872 if (is_unc_volume (name
))
4874 fattrs
= unc_volume_file_attributes (name
);
4878 ctime
= atime
= wtime
= utc_base_ft
;
4882 if (!IS_DIRECTORY_SEP (name
[len
-1]))
4883 strcat (name
, "\\");
4884 if (GetDriveType (name
) < 2)
4890 fattrs
= FILE_ATTRIBUTE_DIRECTORY
;
4891 ctime
= atime
= wtime
= utc_base_ft
;
4897 if (IS_DIRECTORY_SEP (name
[len
-1]))
4900 /* (This is hacky, but helps when doing file completions on
4901 network drives.) Optimize by using information available from
4902 active readdir if possible. */
4903 len
= strlen (dir_pathname
);
4904 if (IS_DIRECTORY_SEP (dir_pathname
[len
-1]))
4906 if (dir_find_handle
!= INVALID_HANDLE_VALUE
4907 && last_dir_find_data
!= -1
4908 && !(is_a_symlink
&& follow_symlinks
)
4909 /* The 2 file-name comparisons below support only ASCII
4910 characters, and will lose (compare not equal) when
4911 the file names include non-ASCII characters that are
4912 the same but for the case. However, doing this
4913 properly involves: (a) converting both file names to
4914 UTF-16, (b) lower-casing both names using CharLowerW,
4915 and (c) comparing the results; this would be quite a
4916 bit slower, whereas Plan B is for users who want
4917 lightweight albeit inaccurate version of 'stat'. */
4918 && c_strncasecmp (save_name
, dir_pathname
, len
) == 0
4919 && IS_DIRECTORY_SEP (name
[len
])
4920 && xstrcasecmp (name
+ len
+ 1, dir_static
.d_name
) == 0)
4922 have_wfd
= last_dir_find_data
;
4923 /* This was the last entry returned by readdir. */
4924 if (last_dir_find_data
== DIR_FIND_DATA_W
)
4925 wfd_w
= dir_find_data_w
;
4927 wfd_a
= dir_find_data_a
;
4931 logon_network_drive (name
);
4933 if (w32_unicode_filenames
)
4935 filename_to_utf16 (name
, name_w
);
4936 fh
= FindFirstFileW (name_w
, &wfd_w
);
4937 have_wfd
= DIR_FIND_DATA_W
;
4941 filename_to_ansi (name
, name_a
);
4942 /* If NAME includes characters not representable by
4943 the current ANSI codepage, filename_to_ansi
4944 usually replaces them with a '?'. We don't want
4945 to let FindFirstFileA interpret those as wildcards,
4946 and "succeed", returning us data from some random
4947 file in the same directory. */
4948 if (_mbspbrk (name_a
, "?"))
4949 fh
= INVALID_HANDLE_VALUE
;
4951 fh
= FindFirstFileA (name_a
, &wfd_a
);
4952 have_wfd
= DIR_FIND_DATA_A
;
4954 if (fh
== INVALID_HANDLE_VALUE
)
4961 /* Note: if NAME is a symlink, the information we get from
4962 FindFirstFile is for the symlink, not its target. */
4963 if (have_wfd
== DIR_FIND_DATA_W
)
4965 fattrs
= wfd_w
.dwFileAttributes
;
4966 ctime
= wfd_w
.ftCreationTime
;
4967 atime
= wfd_w
.ftLastAccessTime
;
4968 wtime
= wfd_w
.ftLastWriteTime
;
4969 fs_high
= wfd_w
.nFileSizeHigh
;
4970 fs_low
= wfd_w
.nFileSizeLow
;
4974 fattrs
= wfd_a
.dwFileAttributes
;
4975 ctime
= wfd_a
.ftCreationTime
;
4976 atime
= wfd_a
.ftLastAccessTime
;
4977 wtime
= wfd_a
.ftLastWriteTime
;
4978 fs_high
= wfd_a
.nFileSizeHigh
;
4979 fs_low
= wfd_a
.nFileSizeLow
;
4983 serialnum
= volume_info
.serialnum
;
4985 if (is_a_symlink
&& !follow_symlinks
)
4986 buf
->st_mode
= S_IFLNK
;
4987 else if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
4988 buf
->st_mode
= S_IFDIR
;
4990 buf
->st_mode
= S_IFREG
;
4992 get_file_owner_and_group (NULL
, buf
);
4995 buf
->st_ino
= fake_inode
;
4997 buf
->st_dev
= serialnum
;
4998 buf
->st_rdev
= serialnum
;
5000 buf
->st_size
= fs_high
;
5001 buf
->st_size
<<= 32;
5002 buf
->st_size
+= fs_low
;
5003 buf
->st_nlink
= nlinks
;
5005 /* Convert timestamps to Unix format. */
5006 buf
->st_mtime
= convert_time (wtime
);
5007 buf
->st_atime
= convert_time (atime
);
5008 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5009 buf
->st_ctime
= convert_time (ctime
);
5010 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5012 /* determine rwx permissions */
5013 if (is_a_symlink
&& !follow_symlinks
)
5014 permission
= S_IREAD
| S_IWRITE
| S_IEXEC
; /* Posix expectations */
5017 if (fattrs
& FILE_ATTRIBUTE_READONLY
)
5018 permission
= S_IREAD
;
5020 permission
= S_IREAD
| S_IWRITE
;
5022 if (fattrs
& FILE_ATTRIBUTE_DIRECTORY
)
5023 permission
|= S_IEXEC
;
5024 else if (is_exec (name
))
5025 permission
|= S_IEXEC
;
5028 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5034 stat (const char * path
, struct stat
* buf
)
5036 return stat_worker (path
, buf
, 1);
5040 lstat (const char * path
, struct stat
* buf
)
5042 return stat_worker (path
, buf
, 0);
5046 fstatat (int fd
, char const *name
, struct stat
*st
, int flags
)
5048 /* Rely on a hack: an open directory is modeled as file descriptor 0.
5049 This is good enough for the current usage in Emacs, but is fragile.
5051 FIXME: Add proper support for fdopendir, fstatat, readlinkat.
5052 Gnulib does this and can serve as a model. */
5053 char fullname
[MAX_UTF8_PATH
];
5057 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5060 errno
= ENAMETOOLONG
;
5066 return stat_worker (name
, st
, ! (flags
& AT_SYMLINK_NOFOLLOW
));
5069 /* Provide fstat and utime as well as stat for consistent handling of
5072 fstat (int desc
, struct stat
* buf
)
5074 HANDLE fh
= (HANDLE
) _get_osfhandle (desc
);
5075 BY_HANDLE_FILE_INFORMATION info
;
5076 unsigned __int64 fake_inode
;
5079 switch (GetFileType (fh
) & ~FILE_TYPE_REMOTE
)
5081 case FILE_TYPE_DISK
:
5082 buf
->st_mode
= S_IFREG
;
5083 if (!GetFileInformationByHandle (fh
, &info
))
5089 case FILE_TYPE_PIPE
:
5090 buf
->st_mode
= S_IFIFO
;
5092 case FILE_TYPE_CHAR
:
5093 case FILE_TYPE_UNKNOWN
:
5095 buf
->st_mode
= S_IFCHR
;
5097 memset (&info
, 0, sizeof (info
));
5098 info
.dwFileAttributes
= 0;
5099 info
.ftCreationTime
= utc_base_ft
;
5100 info
.ftLastAccessTime
= utc_base_ft
;
5101 info
.ftLastWriteTime
= utc_base_ft
;
5104 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5105 buf
->st_mode
= S_IFDIR
;
5107 buf
->st_nlink
= info
.nNumberOfLinks
;
5108 /* Might as well use file index to fake inode values, but this
5109 is not guaranteed to be unique unless we keep a handle open
5110 all the time (even then there are situations where it is
5111 not unique). Reputedly, there are at most 48 bits of info
5112 (on NTFS, presumably less on FAT). */
5113 fake_inode
= info
.nFileIndexHigh
;
5115 fake_inode
+= info
.nFileIndexLow
;
5117 /* MSVC defines _ino_t to be short; other libc's might not. */
5118 if (sizeof (buf
->st_ino
) == 2)
5119 buf
->st_ino
= fake_inode
^ (fake_inode
>> 16);
5121 buf
->st_ino
= fake_inode
;
5123 /* If the caller so requested, get the true file owner and group.
5124 Otherwise, consider the file to belong to the current user. */
5125 if (!w32_stat_get_owner_group
|| is_windows_9x () == TRUE
)
5126 get_file_owner_and_group (NULL
, buf
);
5129 PSECURITY_DESCRIPTOR psd
= NULL
;
5131 psd
= get_file_security_desc_by_handle (fh
);
5134 get_file_owner_and_group (psd
, buf
);
5138 get_file_owner_and_group (NULL
, buf
);
5141 buf
->st_dev
= info
.dwVolumeSerialNumber
;
5142 buf
->st_rdev
= info
.dwVolumeSerialNumber
;
5144 buf
->st_size
= info
.nFileSizeHigh
;
5145 buf
->st_size
<<= 32;
5146 buf
->st_size
+= info
.nFileSizeLow
;
5148 /* Convert timestamps to Unix format. */
5149 buf
->st_mtime
= convert_time (info
.ftLastWriteTime
);
5150 buf
->st_atime
= convert_time (info
.ftLastAccessTime
);
5151 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
5152 buf
->st_ctime
= convert_time (info
.ftCreationTime
);
5153 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
5155 /* determine rwx permissions */
5156 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
5157 permission
= S_IREAD
;
5159 permission
= S_IREAD
| S_IWRITE
;
5161 if (info
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
5162 permission
|= S_IEXEC
;
5165 #if 0 /* no way of knowing the filename */
5166 char * p
= strrchr (name
, '.');
5168 (xstrcasecmp (p
, ".exe") == 0 ||
5169 xstrcasecmp (p
, ".com") == 0 ||
5170 xstrcasecmp (p
, ".bat") == 0 ||
5171 xstrcasecmp (p
, ".cmd") == 0))
5172 permission
|= S_IEXEC
;
5176 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
5181 /* A version of 'utime' which handles directories as well as
5185 utime (const char *name
, struct utimbuf
*times
)
5187 struct utimbuf deftime
;
5194 deftime
.modtime
= deftime
.actime
= time (NULL
);
5198 if (w32_unicode_filenames
)
5200 wchar_t name_utf16
[MAX_PATH
];
5202 if (filename_to_utf16 (name
, name_utf16
) != 0)
5203 return -1; /* errno set by filename_to_utf16 */
5205 /* Need write access to set times. */
5206 fh
= CreateFileW (name_utf16
, FILE_WRITE_ATTRIBUTES
,
5207 /* If NAME specifies a directory, FILE_SHARE_DELETE
5208 allows other processes to delete files inside it,
5209 while we have the directory open. */
5210 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5211 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5215 char name_ansi
[MAX_PATH
];
5217 if (filename_to_ansi (name
, name_ansi
) != 0)
5218 return -1; /* errno set by filename_to_ansi */
5220 fh
= CreateFileA (name_ansi
, FILE_WRITE_ATTRIBUTES
,
5221 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
5222 0, OPEN_EXISTING
, FILE_FLAG_BACKUP_SEMANTICS
, NULL
);
5224 if (fh
!= INVALID_HANDLE_VALUE
)
5226 convert_from_time_t (times
->actime
, &atime
);
5227 convert_from_time_t (times
->modtime
, &mtime
);
5228 if (!SetFileTime (fh
, NULL
, &atime
, &mtime
))
5238 DWORD err
= GetLastError ();
5242 case ERROR_FILE_NOT_FOUND
:
5243 case ERROR_PATH_NOT_FOUND
:
5244 case ERROR_INVALID_DRIVE
:
5245 case ERROR_BAD_NETPATH
:
5246 case ERROR_DEV_NOT_EXIST
:
5247 /* ERROR_INVALID_NAME is the error CreateFile sets when the
5248 file name includes ?s, i.e. translation to ANSI failed. */
5249 case ERROR_INVALID_NAME
:
5252 case ERROR_TOO_MANY_OPEN_FILES
:
5255 case ERROR_ACCESS_DENIED
:
5256 case ERROR_SHARING_VIOLATION
:
5269 /* Symlink-related functions. */
5270 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
5271 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
5275 symlink (char const *filename
, char const *linkname
)
5277 char linkfn
[MAX_UTF8_PATH
], *tgtfn
;
5279 int dir_access
, filename_ends_in_slash
;
5281 /* Diagnostics follows Posix as much as possible. */
5282 if (filename
== NULL
|| linkname
== NULL
)
5292 if (strlen (filename
) > MAX_UTF8_PATH
|| strlen (linkname
) > MAX_UTF8_PATH
)
5294 errno
= ENAMETOOLONG
;
5298 strcpy (linkfn
, map_w32_filename (linkname
, NULL
));
5299 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0)
5305 /* Note: since empty FILENAME was already rejected, we can safely
5306 refer to FILENAME[1]. */
5307 if (!(IS_DIRECTORY_SEP (filename
[0]) || IS_DEVICE_SEP (filename
[1])))
5309 /* Non-absolute FILENAME is understood as being relative to
5310 LINKNAME's directory. We need to prepend that directory to
5311 FILENAME to get correct results from faccessat below, since
5312 otherwise it will interpret FILENAME relative to the
5313 directory where the Emacs process runs. Note that
5314 make-symbolic-link always makes sure LINKNAME is a fully
5315 expanded file name. */
5316 char tem
[MAX_UTF8_PATH
];
5317 char *p
= linkfn
+ strlen (linkfn
);
5319 while (p
> linkfn
&& !IS_ANY_SEP (p
[-1]))
5322 strncpy (tem
, linkfn
, p
- linkfn
);
5323 tem
[p
- linkfn
] = '\0';
5324 strcat (tem
, filename
);
5325 dir_access
= faccessat (AT_FDCWD
, tem
, D_OK
, AT_EACCESS
);
5328 dir_access
= faccessat (AT_FDCWD
, filename
, D_OK
, AT_EACCESS
);
5330 /* Since Windows distinguishes between symlinks to directories and
5331 to files, we provide a kludgy feature: if FILENAME doesn't
5332 exist, but ends in a slash, we create a symlink to directory. If
5333 FILENAME exists and is a directory, we always create a symlink to
5335 filename_ends_in_slash
= IS_DIRECTORY_SEP (filename
[strlen (filename
) - 1]);
5336 if (dir_access
== 0 || filename_ends_in_slash
)
5337 flags
= SYMBOLIC_LINK_FLAG_DIRECTORY
;
5339 tgtfn
= (char *)map_w32_filename (filename
, NULL
);
5340 if (filename_ends_in_slash
)
5341 tgtfn
[strlen (tgtfn
) - 1] = '\0';
5344 if (!create_symbolic_link (linkfn
, tgtfn
, flags
))
5346 /* ENOSYS is set by create_symbolic_link, when it detects that
5347 the OS doesn't support the CreateSymbolicLink API. */
5348 if (errno
!= ENOSYS
)
5350 DWORD w32err
= GetLastError ();
5354 /* ERROR_SUCCESS is sometimes returned when LINKFN and
5355 TGTFN point to the same file name, go figure. */
5357 case ERROR_FILE_EXISTS
:
5360 case ERROR_ACCESS_DENIED
:
5363 case ERROR_FILE_NOT_FOUND
:
5364 case ERROR_PATH_NOT_FOUND
:
5365 case ERROR_BAD_NETPATH
:
5366 case ERROR_INVALID_REPARSE_DATA
:
5369 case ERROR_DIRECTORY
:
5372 case ERROR_PRIVILEGE_NOT_HELD
:
5373 case ERROR_NOT_ALL_ASSIGNED
:
5376 case ERROR_DISK_FULL
:
5389 /* A quick inexpensive test of whether FILENAME identifies a file that
5390 is a symlink. Returns non-zero if it is, zero otherwise. FILENAME
5391 must already be in the normalized form returned by
5394 Note: for repeated operations on many files, it is best to test
5395 whether the underlying volume actually supports symlinks, by
5396 testing the FILE_SUPPORTS_REPARSE_POINTS bit in volume's flags, and
5397 avoid the call to this function if it doesn't. That's because the
5398 call to GetFileAttributes takes a non-negligible time, especially
5399 on non-local or removable filesystems. See stat_worker for an
5400 example of how to do that. */
5402 is_symlink (const char *filename
)
5405 wchar_t filename_w
[MAX_PATH
];
5406 char filename_a
[MAX_PATH
];
5407 WIN32_FIND_DATAW wfdw
;
5408 WIN32_FIND_DATAA wfda
;
5410 int attrs_mean_symlink
;
5412 if (w32_unicode_filenames
)
5414 filename_to_utf16 (filename
, filename_w
);
5415 attrs
= GetFileAttributesW (filename_w
);
5419 filename_to_ansi (filename
, filename_a
);
5420 attrs
= GetFileAttributesA (filename_a
);
5424 DWORD w32err
= GetLastError ();
5428 case ERROR_BAD_NETPATH
: /* network share, can't be a symlink */
5430 case ERROR_ACCESS_DENIED
:
5433 case ERROR_FILE_NOT_FOUND
:
5434 case ERROR_PATH_NOT_FOUND
:
5441 if ((attrs
& FILE_ATTRIBUTE_REPARSE_POINT
) == 0)
5443 logon_network_drive (filename
);
5444 if (w32_unicode_filenames
)
5446 fh
= FindFirstFileW (filename_w
, &wfdw
);
5447 attrs_mean_symlink
=
5448 (wfdw
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5449 && (wfdw
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5451 else if (_mbspbrk (filename_a
, "?"))
5453 /* filename_to_ansi failed to convert the file name. */
5459 fh
= FindFirstFileA (filename_a
, &wfda
);
5460 attrs_mean_symlink
=
5461 (wfda
.dwFileAttributes
& FILE_ATTRIBUTE_REPARSE_POINT
) != 0
5462 && (wfda
.dwReserved0
& IO_REPARSE_TAG_SYMLINK
) == IO_REPARSE_TAG_SYMLINK
;
5464 if (fh
== INVALID_HANDLE_VALUE
)
5467 return attrs_mean_symlink
;
5470 /* If NAME identifies a symbolic link, copy into BUF the file name of
5471 the symlink's target. Copy at most BUF_SIZE bytes, and do NOT
5472 null-terminate the target name, even if it fits. Return the number
5473 of bytes copied, or -1 if NAME is not a symlink or any error was
5474 encountered while resolving it. The file name copied into BUF is
5475 encoded in the current ANSI codepage. */
5477 readlink (const char *name
, char *buf
, size_t buf_size
)
5480 TOKEN_PRIVILEGES privs
;
5481 int restore_privs
= 0;
5484 char resolved
[MAX_UTF8_PATH
];
5497 path
= map_w32_filename (name
, NULL
);
5499 if (strlen (path
) > MAX_UTF8_PATH
)
5501 errno
= ENAMETOOLONG
;
5506 if (is_windows_9x () == TRUE
5507 || (volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) == 0
5508 || !is_symlink (path
))
5511 errno
= EINVAL
; /* not a symlink */
5515 /* Done with simple tests, now we're in for some _real_ work. */
5516 if (enable_privilege (SE_BACKUP_NAME
, TRUE
, &privs
))
5518 /* Implementation note: From here and onward, don't return early,
5519 since that will fail to restore the original set of privileges of
5520 the calling thread. */
5522 retval
= -1; /* not too optimistic, are we? */
5524 /* Note: In the next call to CreateFile, we use zero as the 2nd
5525 argument because, when the symlink is a hidden/system file,
5526 e.g. 'C:\Users\All Users', GENERIC_READ fails with
5527 ERROR_ACCESS_DENIED. Zero seems to work just fine, both for file
5528 and directory symlinks. */
5529 if (w32_unicode_filenames
)
5531 wchar_t path_w
[MAX_PATH
];
5533 filename_to_utf16 (path
, path_w
);
5534 sh
= CreateFileW (path_w
, 0, 0, NULL
, OPEN_EXISTING
,
5535 FILE_FLAG_OPEN_REPARSE_POINT
5536 | FILE_FLAG_BACKUP_SEMANTICS
,
5541 char path_a
[MAX_PATH
];
5543 filename_to_ansi (path
, path_a
);
5544 sh
= CreateFileA (path_a
, 0, 0, NULL
, OPEN_EXISTING
,
5545 FILE_FLAG_OPEN_REPARSE_POINT
5546 | FILE_FLAG_BACKUP_SEMANTICS
,
5549 if (sh
!= INVALID_HANDLE_VALUE
)
5551 BYTE reparse_buf
[MAXIMUM_REPARSE_DATA_BUFFER_SIZE
];
5552 REPARSE_DATA_BUFFER
*reparse_data
= (REPARSE_DATA_BUFFER
*)&reparse_buf
[0];
5555 if (!DeviceIoControl (sh
, FSCTL_GET_REPARSE_POINT
, NULL
, 0,
5556 reparse_buf
, MAXIMUM_REPARSE_DATA_BUFFER_SIZE
,
5559 else if (reparse_data
->ReparseTag
!= IO_REPARSE_TAG_SYMLINK
)
5563 /* Copy the link target name, in wide characters, from
5564 reparse_data, then convert it to multibyte encoding in
5565 the current locale's codepage. */
5569 reparse_data
->SymbolicLinkReparseBuffer
.PrintNameLength
;
5571 reparse_data
->SymbolicLinkReparseBuffer
.PathBuffer
5572 + reparse_data
->SymbolicLinkReparseBuffer
.PrintNameOffset
/sizeof(WCHAR
);
5573 size_t size_to_copy
= buf_size
;
5575 /* According to MSDN, PrintNameLength does not include the
5576 terminating null character. */
5577 lwname
= alloca ((lwname_len
+ 1) * sizeof(WCHAR
));
5578 memcpy (lwname
, lwname_src
, lwname_len
);
5579 lwname
[lwname_len
/sizeof(WCHAR
)] = 0; /* null-terminate */
5580 filename_from_utf16 (lwname
, resolved
);
5581 dostounix_filename (resolved
);
5582 lname_size
= strlen (resolved
) + 1;
5583 if (lname_size
<= buf_size
)
5584 size_to_copy
= lname_size
;
5585 strncpy (buf
, resolved
, size_to_copy
);
5587 retval
= size_to_copy
;
5593 /* CreateFile failed. */
5594 DWORD w32err2
= GetLastError ();
5598 case ERROR_FILE_NOT_FOUND
:
5599 case ERROR_PATH_NOT_FOUND
:
5602 case ERROR_ACCESS_DENIED
:
5603 case ERROR_TOO_MANY_OPEN_FILES
:
5613 restore_privilege (&privs
);
5621 readlinkat (int fd
, char const *name
, char *buffer
,
5624 /* Rely on a hack: an open directory is modeled as file descriptor 0,
5625 as in fstatat. FIXME: Add proper support for readlinkat. */
5626 char fullname
[MAX_UTF8_PATH
];
5630 if (_snprintf (fullname
, sizeof fullname
, "%s/%s", dir_pathname
, name
)
5633 errno
= ENAMETOOLONG
;
5639 return readlink (name
, buffer
, buffer_size
);
5642 /* If FILE is a symlink, return its target (stored in a static
5643 buffer); otherwise return FILE.
5645 This function repeatedly resolves symlinks in the last component of
5646 a chain of symlink file names, as in foo -> bar -> baz -> ...,
5647 until it arrives at a file whose last component is not a symlink,
5648 or some error occurs. It returns the target of the last
5649 successfully resolved symlink in the chain. If it succeeds to
5650 resolve even a single symlink, the value returned is an absolute
5651 file name with backslashes (result of GetFullPathName). By
5652 contrast, if the original FILE is returned, it is unaltered.
5654 Note: This function can set errno even if it succeeds.
5656 Implementation note: we only resolve the last portion ("basename")
5657 of the argument FILE and of each following file in the chain,
5658 disregarding any possible symlinks in its leading directories.
5659 This is because Windows system calls and library functions
5660 transparently resolve symlinks in leading directories and return
5661 correct information, as long as the basename is not a symlink. */
5663 chase_symlinks (const char *file
)
5665 static char target
[MAX_UTF8_PATH
];
5666 char link
[MAX_UTF8_PATH
];
5667 wchar_t target_w
[MAX_PATH
], link_w
[MAX_PATH
];
5668 char target_a
[MAX_PATH
], link_a
[MAX_PATH
];
5669 ssize_t res
, link_len
;
5672 if (is_windows_9x () == TRUE
|| !is_symlink (file
))
5673 return (char *)file
;
5675 if (w32_unicode_filenames
)
5677 wchar_t file_w
[MAX_PATH
];
5679 filename_to_utf16 (file
, file_w
);
5680 if (GetFullPathNameW (file_w
, MAX_PATH
, link_w
, NULL
) == 0)
5681 return (char *)file
;
5682 filename_from_utf16 (link_w
, link
);
5686 char file_a
[MAX_PATH
];
5688 filename_to_ansi (file
, file_a
);
5689 if (GetFullPathNameA (file_a
, MAX_PATH
, link_a
, NULL
) == 0)
5690 return (char *)file
;
5691 filename_from_ansi (link_a
, link
);
5693 link_len
= strlen (link
);
5698 /* Remove trailing slashes, as we want to resolve the last
5699 non-trivial part of the link name. */
5700 while (link_len
> 3 && IS_DIRECTORY_SEP (link
[link_len
-1]))
5701 link
[link_len
--] = '\0';
5703 res
= readlink (link
, target
, MAX_UTF8_PATH
);
5707 if (!(IS_DEVICE_SEP (target
[1])
5708 || (IS_DIRECTORY_SEP (target
[0]) && IS_DIRECTORY_SEP (target
[1]))))
5710 /* Target is relative. Append it to the directory part of
5711 the symlink, then copy the result back to target. */
5712 char *p
= link
+ link_len
;
5714 while (p
> link
&& !IS_ANY_SEP (p
[-1]))
5717 strcpy (target
, link
);
5719 /* Resolve any "." and ".." to get a fully-qualified file name
5721 if (w32_unicode_filenames
)
5723 filename_to_utf16 (target
, target_w
);
5724 link_len
= GetFullPathNameW (target_w
, MAX_PATH
, link_w
, NULL
);
5726 filename_from_utf16 (link_w
, link
);
5730 filename_to_ansi (target
, target_a
);
5731 link_len
= GetFullPathNameA (target_a
, MAX_PATH
, link_a
, NULL
);
5733 filename_from_ansi (link_a
, link
);
5735 link_len
= strlen (link
);
5737 } while (res
> 0 && link_len
> 0 && ++loop_count
<= 100);
5739 if (loop_count
> 100)
5742 if (target
[0] == '\0') /* not a single call to readlink succeeded */
5743 return (char *)file
;
5748 /* Posix ACL emulation. */
5751 acl_valid (acl_t acl
)
5753 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR
)acl
) ? 0 : -1;
5757 acl_to_text (acl_t acl
, ssize_t
*size
)
5760 SECURITY_INFORMATION flags
=
5761 OWNER_SECURITY_INFORMATION
|
5762 GROUP_SECURITY_INFORMATION
|
5763 DACL_SECURITY_INFORMATION
;
5764 char *retval
= NULL
;
5770 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR
)acl
, SDDL_REVISION_1
, flags
, &str_acl
, &local_size
))
5773 /* We don't want to mix heaps, so we duplicate the string in our
5774 heap and free the one allocated by the API. */
5775 retval
= xstrdup (str_acl
);
5778 LocalFree (str_acl
);
5780 else if (errno
!= ENOTSUP
)
5787 acl_from_text (const char *acl_str
)
5789 PSECURITY_DESCRIPTOR psd
, retval
= NULL
;
5795 if (convert_sddl_to_sd (acl_str
, SDDL_REVISION_1
, &psd
, &sd_size
))
5798 retval
= xmalloc (sd_size
);
5799 memcpy (retval
, psd
, sd_size
);
5802 else if (errno
!= ENOTSUP
)
5809 acl_free (void *ptr
)
5816 acl_get_file (const char *fname
, acl_type_t type
)
5818 PSECURITY_DESCRIPTOR psd
= NULL
;
5819 const char *filename
;
5821 if (type
== ACL_TYPE_ACCESS
)
5824 SECURITY_INFORMATION si
=
5825 OWNER_SECURITY_INFORMATION
|
5826 GROUP_SECURITY_INFORMATION
|
5827 DACL_SECURITY_INFORMATION
;
5830 filename
= map_w32_filename (fname
, NULL
);
5831 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5832 fname
= chase_symlinks (filename
);
5837 if (!get_file_security (fname
, si
, psd
, 0, &sd_len
)
5838 && errno
!= ENOTSUP
)
5840 err
= GetLastError ();
5841 if (err
== ERROR_INSUFFICIENT_BUFFER
)
5843 psd
= xmalloc (sd_len
);
5844 if (!get_file_security (fname
, si
, psd
, sd_len
, &sd_len
))
5851 else if (err
== ERROR_FILE_NOT_FOUND
5852 || err
== ERROR_PATH_NOT_FOUND
5853 /* ERROR_INVALID_NAME is what we get if
5854 w32-unicode-filenames is nil and the file cannot
5855 be encoded in the current ANSI codepage. */
5856 || err
== ERROR_INVALID_NAME
)
5864 else if (type
!= ACL_TYPE_DEFAULT
)
5871 acl_set_file (const char *fname
, acl_type_t type
, acl_t acl
)
5873 TOKEN_PRIVILEGES old1
, old2
;
5875 int st
= 0, retval
= -1;
5876 SECURITY_INFORMATION flags
= 0;
5882 const char *filename
;
5884 if (acl_valid (acl
) != 0
5885 || (type
!= ACL_TYPE_DEFAULT
&& type
!= ACL_TYPE_ACCESS
))
5891 if (type
== ACL_TYPE_DEFAULT
)
5897 filename
= map_w32_filename (fname
, NULL
);
5898 if ((volume_info
.flags
& FILE_SUPPORTS_REPARSE_POINTS
) != 0)
5899 fname
= chase_symlinks (filename
);
5903 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5905 flags
|= OWNER_SECURITY_INFORMATION
;
5906 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR
)acl
, &psid
, &dflt
)
5908 flags
|= GROUP_SECURITY_INFORMATION
;
5909 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR
)acl
, &dacl_present
,
5912 flags
|= DACL_SECURITY_INFORMATION
;
5916 /* According to KB-245153, setting the owner will succeed if either:
5917 (1) the caller is the user who will be the new owner, and has the
5918 SE_TAKE_OWNERSHIP privilege, or
5919 (2) the caller has the SE_RESTORE privilege, in which case she can
5920 set any valid user or group as the owner
5922 We request below both SE_TAKE_OWNERSHIP and SE_RESTORE
5923 privileges, and disregard any failures in obtaining them. If
5924 these privileges cannot be obtained, and do not already exist in
5925 the calling thread's security token, this function could fail
5927 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME
, TRUE
, &old1
))
5929 if (enable_privilege (SE_RESTORE_NAME
, TRUE
, &old2
))
5934 if (!set_file_security (fname
, flags
, (PSECURITY_DESCRIPTOR
)acl
))
5936 err
= GetLastError ();
5938 if (errno
== ENOTSUP
)
5940 else if (err
== ERROR_INVALID_OWNER
5941 || err
== ERROR_NOT_ALL_ASSIGNED
5942 || err
== ERROR_ACCESS_DENIED
)
5944 /* Maybe the requested ACL and the one the file already has
5945 are identical, in which case we can silently ignore the
5946 failure. (And no, Windows doesn't.) */
5947 acl_t current_acl
= acl_get_file (fname
, ACL_TYPE_ACCESS
);
5952 char *acl_from
= acl_to_text (current_acl
, NULL
);
5953 char *acl_to
= acl_to_text (acl
, NULL
);
5955 if (acl_from
&& acl_to
&& xstrcasecmp (acl_from
, acl_to
) == 0)
5961 acl_free (acl_from
);
5964 acl_free (current_acl
);
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 be
5971 encoded in the current ANSI codepage. */
5972 || err
== ERROR_INVALID_NAME
)
5986 restore_privilege (&old2
);
5987 restore_privilege (&old1
);
5995 /* MS-Windows version of careadlinkat (cf. ../lib/careadlinkat.c). We
5996 have a fixed max size for file names, so we don't need the kind of
5997 alloc/malloc/realloc dance the gnulib version does. We also don't
5998 support FD-relative symlinks. */
6000 careadlinkat (int fd
, char const *filename
,
6001 char *buffer
, size_t buffer_size
,
6002 struct allocator
const *alloc
,
6003 ssize_t (*preadlinkat
) (int, char const *, char *, size_t))
6005 char linkname
[MAX_UTF8_PATH
];
6008 link_size
= preadlinkat (fd
, filename
, linkname
, sizeof(linkname
));
6012 char *retval
= buffer
;
6014 linkname
[link_size
++] = '\0';
6015 if (link_size
> buffer_size
)
6016 retval
= (char *)(alloc
? alloc
->allocate
: xmalloc
) (link_size
);
6018 memcpy (retval
, linkname
, link_size
);
6026 w32_copy_file (const char *from
, const char *to
,
6027 int keep_time
, int preserve_ownership
, int copy_acls
)
6031 wchar_t from_w
[MAX_PATH
], to_w
[MAX_PATH
];
6032 char from_a
[MAX_PATH
], to_a
[MAX_PATH
];
6034 /* We ignore preserve_ownership for now. */
6035 preserve_ownership
= preserve_ownership
;
6039 acl
= acl_get_file (from
, ACL_TYPE_ACCESS
);
6040 if (acl
== NULL
&& acl_errno_valid (errno
))
6043 if (w32_unicode_filenames
)
6045 filename_to_utf16 (from
, from_w
);
6046 filename_to_utf16 (to
, to_w
);
6047 copy_result
= CopyFileW (from_w
, to_w
, FALSE
);
6051 filename_to_ansi (from
, from_a
);
6052 filename_to_ansi (to
, to_a
);
6053 copy_result
= CopyFileA (from_a
, to_a
, FALSE
);
6057 /* CopyFile doesn't set errno when it fails. By far the most
6058 "popular" reason is that the target is read-only. */
6059 DWORD err
= GetLastError ();
6063 case ERROR_FILE_NOT_FOUND
:
6066 case ERROR_ACCESS_DENIED
:
6069 case ERROR_ENCRYPTION_FAILED
:
6081 /* CopyFile retains the timestamp by default. However, see
6082 "Community Additions" for CopyFile: it sounds like that is not
6083 entirely true. Testing on Windows XP confirms that modified time
6084 is copied, but creation and last-access times are not.
6086 else if (!keep_time
)
6088 struct timespec now
;
6091 if (w32_unicode_filenames
)
6093 /* Ensure file is writable while its times are set. */
6094 attributes
= GetFileAttributesW (to_w
);
6095 SetFileAttributesW (to_w
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6096 now
= current_timespec ();
6097 if (set_file_times (-1, to
, now
, now
))
6099 /* Restore original attributes. */
6100 SetFileAttributesW (to_w
, attributes
);
6105 /* Restore original attributes. */
6106 SetFileAttributesW (to_w
, attributes
);
6110 attributes
= GetFileAttributesA (to_a
);
6111 SetFileAttributesA (to_a
, attributes
& ~FILE_ATTRIBUTE_READONLY
);
6112 now
= current_timespec ();
6113 if (set_file_times (-1, to
, now
, now
))
6115 SetFileAttributesA (to_a
, attributes
);
6120 SetFileAttributesA (to_a
, attributes
);
6126 acl_set_file (to
, ACL_TYPE_ACCESS
, acl
) != 0;
6128 if (fail
&& acl_errno_valid (errno
))
6136 /* Support for browsing other processes and their attributes. See
6137 process.c for the Lisp bindings. */
6139 /* Helper wrapper functions. */
6141 static HANDLE WINAPI
6142 create_toolhelp32_snapshot (DWORD Flags
, DWORD Ignored
)
6144 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot
= NULL
;
6146 if (g_b_init_create_toolhelp32_snapshot
== 0)
6148 g_b_init_create_toolhelp32_snapshot
= 1;
6149 s_pfn_Create_Toolhelp32_Snapshot
= (CreateToolhelp32Snapshot_Proc
)
6150 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6151 "CreateToolhelp32Snapshot");
6153 if (s_pfn_Create_Toolhelp32_Snapshot
== NULL
)
6155 return INVALID_HANDLE_VALUE
;
6157 return (s_pfn_Create_Toolhelp32_Snapshot (Flags
, Ignored
));
6161 process32_first (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6163 static Process32First_Proc s_pfn_Process32_First
= NULL
;
6165 if (g_b_init_process32_first
== 0)
6167 g_b_init_process32_first
= 1;
6168 s_pfn_Process32_First
= (Process32First_Proc
)
6169 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6172 if (s_pfn_Process32_First
== NULL
)
6176 return (s_pfn_Process32_First (hSnapshot
, lppe
));
6180 process32_next (HANDLE hSnapshot
, LPPROCESSENTRY32 lppe
)
6182 static Process32Next_Proc s_pfn_Process32_Next
= NULL
;
6184 if (g_b_init_process32_next
== 0)
6186 g_b_init_process32_next
= 1;
6187 s_pfn_Process32_Next
= (Process32Next_Proc
)
6188 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6191 if (s_pfn_Process32_Next
== NULL
)
6195 return (s_pfn_Process32_Next (hSnapshot
, lppe
));
6199 open_thread_token (HANDLE ThreadHandle
,
6200 DWORD DesiredAccess
,
6202 PHANDLE TokenHandle
)
6204 static OpenThreadToken_Proc s_pfn_Open_Thread_Token
= NULL
;
6205 HMODULE hm_advapi32
= NULL
;
6206 if (is_windows_9x () == TRUE
)
6208 SetLastError (ERROR_NOT_SUPPORTED
);
6211 if (g_b_init_open_thread_token
== 0)
6213 g_b_init_open_thread_token
= 1;
6214 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6215 s_pfn_Open_Thread_Token
=
6216 (OpenThreadToken_Proc
) GetProcAddress (hm_advapi32
, "OpenThreadToken");
6218 if (s_pfn_Open_Thread_Token
== NULL
)
6220 SetLastError (ERROR_NOT_SUPPORTED
);
6224 s_pfn_Open_Thread_Token (
6233 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
6235 static ImpersonateSelf_Proc s_pfn_Impersonate_Self
= NULL
;
6236 HMODULE hm_advapi32
= NULL
;
6237 if (is_windows_9x () == TRUE
)
6241 if (g_b_init_impersonate_self
== 0)
6243 g_b_init_impersonate_self
= 1;
6244 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6245 s_pfn_Impersonate_Self
=
6246 (ImpersonateSelf_Proc
) GetProcAddress (hm_advapi32
, "ImpersonateSelf");
6248 if (s_pfn_Impersonate_Self
== NULL
)
6252 return s_pfn_Impersonate_Self (ImpersonationLevel
);
6256 revert_to_self (void)
6258 static RevertToSelf_Proc s_pfn_Revert_To_Self
= NULL
;
6259 HMODULE hm_advapi32
= NULL
;
6260 if (is_windows_9x () == TRUE
)
6264 if (g_b_init_revert_to_self
== 0)
6266 g_b_init_revert_to_self
= 1;
6267 hm_advapi32
= LoadLibrary ("Advapi32.dll");
6268 s_pfn_Revert_To_Self
=
6269 (RevertToSelf_Proc
) GetProcAddress (hm_advapi32
, "RevertToSelf");
6271 if (s_pfn_Revert_To_Self
== NULL
)
6275 return s_pfn_Revert_To_Self ();
6279 get_process_memory_info (HANDLE h_proc
,
6280 PPROCESS_MEMORY_COUNTERS mem_counters
,
6283 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info
= NULL
;
6284 HMODULE hm_psapi
= NULL
;
6285 if (is_windows_9x () == TRUE
)
6289 if (g_b_init_get_process_memory_info
== 0)
6291 g_b_init_get_process_memory_info
= 1;
6292 hm_psapi
= LoadLibrary ("Psapi.dll");
6294 s_pfn_Get_Process_Memory_Info
= (GetProcessMemoryInfo_Proc
)
6295 GetProcAddress (hm_psapi
, "GetProcessMemoryInfo");
6297 if (s_pfn_Get_Process_Memory_Info
== NULL
)
6301 return s_pfn_Get_Process_Memory_Info (h_proc
, mem_counters
, bufsize
);
6305 get_process_working_set_size (HANDLE h_proc
,
6309 static GetProcessWorkingSetSize_Proc
6310 s_pfn_Get_Process_Working_Set_Size
= NULL
;
6312 if (is_windows_9x () == TRUE
)
6316 if (g_b_init_get_process_working_set_size
== 0)
6318 g_b_init_get_process_working_set_size
= 1;
6319 s_pfn_Get_Process_Working_Set_Size
= (GetProcessWorkingSetSize_Proc
)
6320 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6321 "GetProcessWorkingSetSize");
6323 if (s_pfn_Get_Process_Working_Set_Size
== NULL
)
6327 return s_pfn_Get_Process_Working_Set_Size (h_proc
, minrss
, maxrss
);
6331 global_memory_status (MEMORYSTATUS
*buf
)
6333 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status
= NULL
;
6335 if (is_windows_9x () == TRUE
)
6339 if (g_b_init_global_memory_status
== 0)
6341 g_b_init_global_memory_status
= 1;
6342 s_pfn_Global_Memory_Status
= (GlobalMemoryStatus_Proc
)
6343 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6344 "GlobalMemoryStatus");
6346 if (s_pfn_Global_Memory_Status
== NULL
)
6350 return s_pfn_Global_Memory_Status (buf
);
6354 global_memory_status_ex (MEMORY_STATUS_EX
*buf
)
6356 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex
= NULL
;
6358 if (is_windows_9x () == TRUE
)
6362 if (g_b_init_global_memory_status_ex
== 0)
6364 g_b_init_global_memory_status_ex
= 1;
6365 s_pfn_Global_Memory_Status_Ex
= (GlobalMemoryStatusEx_Proc
)
6366 GetProcAddress (GetModuleHandle ("kernel32.dll"),
6367 "GlobalMemoryStatusEx");
6369 if (s_pfn_Global_Memory_Status_Ex
== NULL
)
6373 return s_pfn_Global_Memory_Status_Ex (buf
);
6377 list_system_processes (void)
6379 struct gcpro gcpro1
;
6380 Lisp_Object proclist
= Qnil
;
6383 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6385 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6387 PROCESSENTRY32 proc_entry
;
6393 proc_entry
.dwSize
= sizeof (PROCESSENTRY32
);
6394 for (res
= process32_first (h_snapshot
, &proc_entry
); res
;
6395 res
= process32_next (h_snapshot
, &proc_entry
))
6397 proc_id
= proc_entry
.th32ProcessID
;
6398 proclist
= Fcons (make_fixnum_or_float (proc_id
), proclist
);
6401 CloseHandle (h_snapshot
);
6403 proclist
= Fnreverse (proclist
);
6410 enable_privilege (LPCTSTR priv_name
, BOOL enable_p
, TOKEN_PRIVILEGES
*old_priv
)
6412 TOKEN_PRIVILEGES priv
;
6413 DWORD priv_size
= sizeof (priv
);
6414 DWORD opriv_size
= sizeof (*old_priv
);
6415 HANDLE h_token
= NULL
;
6416 HANDLE h_thread
= GetCurrentThread ();
6420 res
= open_thread_token (h_thread
,
6421 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6423 if (!res
&& GetLastError () == ERROR_NO_TOKEN
)
6425 if (impersonate_self (SecurityImpersonation
))
6426 res
= open_thread_token (h_thread
,
6427 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6432 priv
.PrivilegeCount
= 1;
6433 priv
.Privileges
[0].Attributes
= enable_p
? SE_PRIVILEGE_ENABLED
: 0;
6434 LookupPrivilegeValue (NULL
, priv_name
, &priv
.Privileges
[0].Luid
);
6435 if (AdjustTokenPrivileges (h_token
, FALSE
, &priv
, priv_size
,
6436 old_priv
, &opriv_size
)
6437 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6441 CloseHandle (h_token
);
6447 restore_privilege (TOKEN_PRIVILEGES
*priv
)
6449 DWORD priv_size
= sizeof (*priv
);
6450 HANDLE h_token
= NULL
;
6453 if (open_thread_token (GetCurrentThread (),
6454 TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
,
6457 if (AdjustTokenPrivileges (h_token
, FALSE
, priv
, priv_size
, NULL
, NULL
)
6458 && GetLastError () != ERROR_NOT_ALL_ASSIGNED
)
6462 CloseHandle (h_token
);
6468 ltime (ULONGLONG time_100ns
)
6470 ULONGLONG time_sec
= time_100ns
/ 10000000;
6471 int subsec
= time_100ns
% 10000000;
6472 return list4i (time_sec
>> 16, time_sec
& 0xffff,
6473 subsec
/ 10, subsec
% 10 * 100000);
6476 #define U64_TO_LISP_TIME(time) ltime (time)
6479 process_times (HANDLE h_proc
, Lisp_Object
*ctime
, Lisp_Object
*etime
,
6480 Lisp_Object
*stime
, Lisp_Object
*utime
, Lisp_Object
*ttime
,
6483 FILETIME ft_creation
, ft_exit
, ft_kernel
, ft_user
, ft_current
;
6484 ULONGLONG tem1
, tem2
, tem3
, tem
;
6487 || !get_process_times_fn
6488 || !(*get_process_times_fn
) (h_proc
, &ft_creation
, &ft_exit
,
6489 &ft_kernel
, &ft_user
))
6492 GetSystemTimeAsFileTime (&ft_current
);
6494 FILETIME_TO_U64 (tem1
, ft_kernel
);
6495 *stime
= U64_TO_LISP_TIME (tem1
);
6497 FILETIME_TO_U64 (tem2
, ft_user
);
6498 *utime
= U64_TO_LISP_TIME (tem2
);
6501 *ttime
= U64_TO_LISP_TIME (tem3
);
6503 FILETIME_TO_U64 (tem
, ft_creation
);
6504 /* Process no 4 (System) returns zero creation time. */
6507 *ctime
= U64_TO_LISP_TIME (tem
);
6511 FILETIME_TO_U64 (tem3
, ft_current
);
6512 tem
= (tem3
- utc_base
) - tem
;
6514 *etime
= U64_TO_LISP_TIME (tem
);
6518 *pcpu
= 100.0 * (tem1
+ tem2
) / tem
;
6529 system_process_attributes (Lisp_Object pid
)
6531 struct gcpro gcpro1
, gcpro2
, gcpro3
;
6532 Lisp_Object attrs
= Qnil
;
6533 Lisp_Object cmd_str
, decoded_cmd
, tem
;
6534 HANDLE h_snapshot
, h_proc
;
6537 char uname
[UNLEN
+1], gname
[GNLEN
+1], domain
[1025];
6538 DWORD ulength
= sizeof (uname
), dlength
= sizeof (domain
), needed
;
6539 DWORD glength
= sizeof (gname
);
6540 HANDLE token
= NULL
;
6541 SID_NAME_USE user_type
;
6542 unsigned char *buf
= NULL
;
6544 TOKEN_USER user_token
;
6545 TOKEN_PRIMARY_GROUP group_token
;
6548 PROCESS_MEMORY_COUNTERS mem
;
6549 PROCESS_MEMORY_COUNTERS_EX mem_ex
;
6550 SIZE_T minrss
, maxrss
;
6552 MEMORY_STATUS_EX memstex
;
6553 double totphys
= 0.0;
6554 Lisp_Object ctime
, stime
, utime
, etime
, ttime
;
6556 BOOL result
= FALSE
;
6558 CHECK_NUMBER_OR_FLOAT (pid
);
6559 proc_id
= FLOATP (pid
) ? XFLOAT_DATA (pid
) : XINT (pid
);
6561 h_snapshot
= create_toolhelp32_snapshot (TH32CS_SNAPPROCESS
, 0);
6563 GCPRO3 (attrs
, decoded_cmd
, tem
);
6565 if (h_snapshot
!= INVALID_HANDLE_VALUE
)
6570 pe
.dwSize
= sizeof (PROCESSENTRY32
);
6571 for (res
= process32_first (h_snapshot
, &pe
); res
;
6572 res
= process32_next (h_snapshot
, &pe
))
6574 if (proc_id
== pe
.th32ProcessID
)
6577 decoded_cmd
= build_string ("Idle");
6580 /* Decode the command name from locale-specific
6582 cmd_str
= build_unibyte_string (pe
.szExeFile
);
6585 code_convert_string_norecord (cmd_str
,
6586 Vlocale_coding_system
, 0);
6588 attrs
= Fcons (Fcons (Qcomm
, decoded_cmd
), attrs
);
6589 attrs
= Fcons (Fcons (Qppid
,
6590 make_fixnum_or_float (pe
.th32ParentProcessID
)),
6592 attrs
= Fcons (Fcons (Qpri
, make_number (pe
.pcPriClassBase
)),
6594 attrs
= Fcons (Fcons (Qthcount
,
6595 make_fixnum_or_float (pe
.cntThreads
)),
6602 CloseHandle (h_snapshot
);
6611 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6613 /* If we were denied a handle to the process, try again after
6614 enabling the SeDebugPrivilege in our process. */
6617 TOKEN_PRIVILEGES priv_current
;
6619 if (enable_privilege (SE_DEBUG_NAME
, TRUE
, &priv_current
))
6621 h_proc
= OpenProcess (PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
,
6623 restore_privilege (&priv_current
);
6629 result
= open_process_token (h_proc
, TOKEN_QUERY
, &token
);
6632 result
= get_token_information (token
, TokenUser
, NULL
, 0, &blen
);
6633 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6635 buf
= xmalloc (blen
);
6636 result
= get_token_information (token
, TokenUser
,
6637 (LPVOID
)buf
, blen
, &needed
);
6640 memcpy (&user_token
, buf
, sizeof (user_token
));
6641 if (!w32_cached_id (user_token
.User
.Sid
, &euid
, uname
))
6643 euid
= get_rid (user_token
.User
.Sid
);
6644 result
= lookup_account_sid (NULL
, user_token
.User
.Sid
,
6649 w32_add_to_cache (user_token
.User
.Sid
, euid
, uname
);
6652 strcpy (uname
, "unknown");
6656 ulength
= strlen (uname
);
6662 /* Determine a reasonable euid and gid values. */
6663 if (xstrcasecmp ("administrator", uname
) == 0)
6665 euid
= 500; /* well-known Administrator uid */
6666 egid
= 513; /* well-known None gid */
6670 /* Get group id and name. */
6671 result
= get_token_information (token
, TokenPrimaryGroup
,
6672 (LPVOID
)buf
, blen
, &needed
);
6673 if (!result
&& GetLastError () == ERROR_INSUFFICIENT_BUFFER
)
6675 buf
= xrealloc (buf
, blen
= needed
);
6676 result
= get_token_information (token
, TokenPrimaryGroup
,
6677 (LPVOID
)buf
, blen
, &needed
);
6681 memcpy (&group_token
, buf
, sizeof (group_token
));
6682 if (!w32_cached_id (group_token
.PrimaryGroup
, &egid
, gname
))
6684 egid
= get_rid (group_token
.PrimaryGroup
);
6685 dlength
= sizeof (domain
);
6687 lookup_account_sid (NULL
, group_token
.PrimaryGroup
,
6688 gname
, &glength
, NULL
, &dlength
,
6691 w32_add_to_cache (group_token
.PrimaryGroup
,
6695 strcpy (gname
, "None");
6699 glength
= strlen (gname
);
6707 if (!is_windows_9x ())
6709 /* We couldn't open the process token, presumably because of
6710 insufficient access rights. Assume this process is run
6712 strcpy (uname
, "SYSTEM");
6713 strcpy (gname
, "None");
6714 euid
= 18; /* SYSTEM */
6715 egid
= 513; /* None */
6716 glength
= strlen (gname
);
6717 ulength
= strlen (uname
);
6719 /* If we are running under Windows 9X, where security calls are
6720 not supported, we assume all processes are run by the current
6722 else if (GetUserName (uname
, &ulength
))
6724 if (xstrcasecmp ("administrator", uname
) == 0)
6729 strcpy (gname
, "None");
6730 glength
= strlen (gname
);
6731 ulength
= strlen (uname
);
6737 strcpy (uname
, "administrator");
6738 ulength
= strlen (uname
);
6739 strcpy (gname
, "None");
6740 glength
= strlen (gname
);
6743 CloseHandle (token
);
6746 attrs
= Fcons (Fcons (Qeuid
, make_fixnum_or_float (euid
)), attrs
);
6747 tem
= make_unibyte_string (uname
, ulength
);
6748 attrs
= Fcons (Fcons (Quser
,
6749 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6751 attrs
= Fcons (Fcons (Qegid
, make_fixnum_or_float (egid
)), attrs
);
6752 tem
= make_unibyte_string (gname
, glength
);
6753 attrs
= Fcons (Fcons (Qgroup
,
6754 code_convert_string_norecord (tem
, Vlocale_coding_system
, 0)),
6757 if (global_memory_status_ex (&memstex
))
6758 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
6759 totphys
= memstex
.ullTotalPhys
/ 1024.0;
6761 /* Visual Studio 6 cannot convert an unsigned __int64 type to
6762 double, so we need to do this for it... */
6764 DWORD tot_hi
= memstex
.ullTotalPhys
>> 32;
6765 DWORD tot_md
= (memstex
.ullTotalPhys
& 0x00000000ffffffff) >> 10;
6766 DWORD tot_lo
= memstex
.ullTotalPhys
% 1024;
6768 totphys
= tot_hi
* 4194304.0 + tot_md
+ tot_lo
/ 1024.0;
6770 #endif /* __GNUC__ || _MSC_VER >= 1300 */
6771 else if (global_memory_status (&memst
))
6772 totphys
= memst
.dwTotalPhys
/ 1024.0;
6775 && get_process_memory_info (h_proc
, (PROCESS_MEMORY_COUNTERS
*)&mem_ex
,
6778 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6780 attrs
= Fcons (Fcons (Qmajflt
,
6781 make_fixnum_or_float (mem_ex
.PageFaultCount
)),
6783 attrs
= Fcons (Fcons (Qvsize
,
6784 make_fixnum_or_float (mem_ex
.PrivateUsage
/ 1024)),
6786 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6788 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6791 && get_process_memory_info (h_proc
, &mem
, sizeof (mem
)))
6793 SIZE_T rss
= mem_ex
.WorkingSetSize
/ 1024;
6795 attrs
= Fcons (Fcons (Qmajflt
,
6796 make_fixnum_or_float (mem
.PageFaultCount
)),
6798 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (rss
)), attrs
);
6800 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6803 && get_process_working_set_size (h_proc
, &minrss
, &maxrss
))
6805 DWORD rss
= maxrss
/ 1024;
6807 attrs
= Fcons (Fcons (Qrss
, make_fixnum_or_float (maxrss
/ 1024)), attrs
);
6809 attrs
= Fcons (Fcons (Qpmem
, make_float (100. * rss
/ totphys
)), attrs
);
6812 if (process_times (h_proc
, &ctime
, &etime
, &stime
, &utime
, &ttime
, &pcpu
))
6814 attrs
= Fcons (Fcons (Qutime
, utime
), attrs
);
6815 attrs
= Fcons (Fcons (Qstime
, stime
), attrs
);
6816 attrs
= Fcons (Fcons (Qtime
, ttime
), attrs
);
6817 attrs
= Fcons (Fcons (Qstart
, ctime
), attrs
);
6818 attrs
= Fcons (Fcons (Qetime
, etime
), attrs
);
6819 attrs
= Fcons (Fcons (Qpcpu
, make_float (pcpu
)), attrs
);
6822 /* FIXME: Retrieve command line by walking the PEB of the process. */
6825 CloseHandle (h_proc
);
6831 /* Wrappers for winsock functions to map between our file descriptors
6832 and winsock's handles; also set h_errno for convenience.
6834 To allow Emacs to run on systems which don't have winsock support
6835 installed, we dynamically link to winsock on startup if present, and
6836 otherwise provide the minimum necessary functionality
6837 (eg. gethostname). */
6839 /* function pointers for relevant socket functions */
6840 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
6841 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
6842 int (PASCAL
*pfn_WSAGetLastError
) (void);
6843 int (PASCAL
*pfn_WSAEventSelect
) (SOCKET s
, HANDLE hEventObject
, long lNetworkEvents
);
6844 HANDLE (PASCAL
*pfn_WSACreateEvent
) (void);
6845 int (PASCAL
*pfn_WSACloseEvent
) (HANDLE hEvent
);
6846 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
6847 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6848 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
6849 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
6850 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
6851 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
6852 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
6853 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
6854 int (PASCAL
*pfn_WSACleanup
) (void);
6856 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
6857 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
6858 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
6859 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
6860 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
6861 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
6862 int (PASCAL
*pfn_getpeername
) (SOCKET s
, struct sockaddr
*addr
, int * namelen
);
6863 int (PASCAL
*pfn_setsockopt
) (SOCKET s
, int level
, int optname
,
6864 const char * optval
, int optlen
);
6865 int (PASCAL
*pfn_listen
) (SOCKET s
, int backlog
);
6866 int (PASCAL
*pfn_getsockname
) (SOCKET s
, struct sockaddr
* name
,
6868 SOCKET (PASCAL
*pfn_accept
) (SOCKET s
, struct sockaddr
* addr
, int * addrlen
);
6869 int (PASCAL
*pfn_recvfrom
) (SOCKET s
, char * buf
, int len
, int flags
,
6870 struct sockaddr
* from
, int * fromlen
);
6871 int (PASCAL
*pfn_sendto
) (SOCKET s
, const char * buf
, int len
, int flags
,
6872 const struct sockaddr
* to
, int tolen
);
6874 /* SetHandleInformation is only needed to make sockets non-inheritable. */
6875 BOOL (WINAPI
*pfn_SetHandleInformation
) (HANDLE object
, DWORD mask
, DWORD flags
);
6876 #ifndef HANDLE_FLAG_INHERIT
6877 #define HANDLE_FLAG_INHERIT 1
6881 static int winsock_inuse
;
6886 if (winsock_lib
!= NULL
&& winsock_inuse
== 0)
6888 release_listen_threads ();
6889 /* Not sure what would cause WSAENETDOWN, or even if it can happen
6890 after WSAStartup returns successfully, but it seems reasonable
6891 to allow unloading winsock anyway in that case. */
6892 if (pfn_WSACleanup () == 0 ||
6893 pfn_WSAGetLastError () == WSAENETDOWN
)
6895 if (FreeLibrary (winsock_lib
))
6904 init_winsock (int load_now
)
6906 WSADATA winsockData
;
6908 if (winsock_lib
!= NULL
)
6911 pfn_SetHandleInformation
6912 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
6913 "SetHandleInformation");
6915 winsock_lib
= LoadLibrary ("Ws2_32.dll");
6917 if (winsock_lib
!= NULL
)
6919 /* dynamically link to socket functions */
6921 #define LOAD_PROC(fn) \
6922 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
6925 LOAD_PROC (WSAStartup
);
6926 LOAD_PROC (WSASetLastError
);
6927 LOAD_PROC (WSAGetLastError
);
6928 LOAD_PROC (WSAEventSelect
);
6929 LOAD_PROC (WSACreateEvent
);
6930 LOAD_PROC (WSACloseEvent
);
6933 LOAD_PROC (connect
);
6934 LOAD_PROC (ioctlsocket
);
6937 LOAD_PROC (closesocket
);
6938 LOAD_PROC (shutdown
);
6941 LOAD_PROC (inet_addr
);
6942 LOAD_PROC (gethostname
);
6943 LOAD_PROC (gethostbyname
);
6944 LOAD_PROC (getservbyname
);
6945 LOAD_PROC (getpeername
);
6946 LOAD_PROC (WSACleanup
);
6947 LOAD_PROC (setsockopt
);
6949 LOAD_PROC (getsockname
);
6951 LOAD_PROC (recvfrom
);
6955 /* specify version 1.1 of winsock */
6956 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
6958 if (winsockData
.wVersion
!= 0x101)
6963 /* Report that winsock exists and is usable, but leave
6964 socket functions disabled. I am assuming that calling
6965 WSAStartup does not require any network interaction,
6966 and in particular does not cause or require a dial-up
6967 connection to be established. */
6970 FreeLibrary (winsock_lib
);
6978 FreeLibrary (winsock_lib
);
6988 /* Function to map winsock error codes to errno codes for those errno
6989 code defined in errno.h (errno values not defined by errno.h are
6990 already in nt/inc/sys/socket.h). */
6997 if (winsock_lib
== NULL
)
7000 wsa_err
= pfn_WSAGetLastError ();
7004 case WSAEACCES
: errno
= EACCES
; break;
7005 case WSAEBADF
: errno
= EBADF
; break;
7006 case WSAEFAULT
: errno
= EFAULT
; break;
7007 case WSAEINTR
: errno
= EINTR
; break;
7008 case WSAEINVAL
: errno
= EINVAL
; break;
7009 case WSAEMFILE
: errno
= EMFILE
; break;
7010 case WSAENAMETOOLONG
: errno
= ENAMETOOLONG
; break;
7011 case WSAENOTEMPTY
: errno
= ENOTEMPTY
; break;
7012 default: errno
= wsa_err
; break;
7020 if (winsock_lib
!= NULL
)
7021 pfn_WSASetLastError (0);
7024 /* Extend strerror to handle the winsock-specific error codes. */
7028 } _wsa_errlist
[] = {
7029 {WSAEINTR
, "Interrupted function call"},
7030 {WSAEBADF
, "Bad file descriptor"},
7031 {WSAEACCES
, "Permission denied"},
7032 {WSAEFAULT
, "Bad address"},
7033 {WSAEINVAL
, "Invalid argument"},
7034 {WSAEMFILE
, "Too many open files"},
7036 {WSAEWOULDBLOCK
, "Resource temporarily unavailable"},
7037 {WSAEINPROGRESS
, "Operation now in progress"},
7038 {WSAEALREADY
, "Operation already in progress"},
7039 {WSAENOTSOCK
, "Socket operation on non-socket"},
7040 {WSAEDESTADDRREQ
, "Destination address required"},
7041 {WSAEMSGSIZE
, "Message too long"},
7042 {WSAEPROTOTYPE
, "Protocol wrong type for socket"},
7043 {WSAENOPROTOOPT
, "Bad protocol option"},
7044 {WSAEPROTONOSUPPORT
, "Protocol not supported"},
7045 {WSAESOCKTNOSUPPORT
, "Socket type not supported"},
7046 {WSAEOPNOTSUPP
, "Operation not supported"},
7047 {WSAEPFNOSUPPORT
, "Protocol family not supported"},
7048 {WSAEAFNOSUPPORT
, "Address family not supported by protocol family"},
7049 {WSAEADDRINUSE
, "Address already in use"},
7050 {WSAEADDRNOTAVAIL
, "Cannot assign requested address"},
7051 {WSAENETDOWN
, "Network is down"},
7052 {WSAENETUNREACH
, "Network is unreachable"},
7053 {WSAENETRESET
, "Network dropped connection on reset"},
7054 {WSAECONNABORTED
, "Software caused connection abort"},
7055 {WSAECONNRESET
, "Connection reset by peer"},
7056 {WSAENOBUFS
, "No buffer space available"},
7057 {WSAEISCONN
, "Socket is already connected"},
7058 {WSAENOTCONN
, "Socket is not connected"},
7059 {WSAESHUTDOWN
, "Cannot send after socket shutdown"},
7060 {WSAETOOMANYREFS
, "Too many references"}, /* not sure */
7061 {WSAETIMEDOUT
, "Connection timed out"},
7062 {WSAECONNREFUSED
, "Connection refused"},
7063 {WSAELOOP
, "Network loop"}, /* not sure */
7064 {WSAENAMETOOLONG
, "Name is too long"},
7065 {WSAEHOSTDOWN
, "Host is down"},
7066 {WSAEHOSTUNREACH
, "No route to host"},
7067 {WSAENOTEMPTY
, "Buffer not empty"}, /* not sure */
7068 {WSAEPROCLIM
, "Too many processes"},
7069 {WSAEUSERS
, "Too many users"}, /* not sure */
7070 {WSAEDQUOT
, "Double quote in host name"}, /* really not sure */
7071 {WSAESTALE
, "Data is stale"}, /* not sure */
7072 {WSAEREMOTE
, "Remote error"}, /* not sure */
7074 {WSASYSNOTREADY
, "Network subsystem is unavailable"},
7075 {WSAVERNOTSUPPORTED
, "WINSOCK.DLL version out of range"},
7076 {WSANOTINITIALISED
, "Winsock not initialized successfully"},
7077 {WSAEDISCON
, "Graceful shutdown in progress"},
7079 {WSAENOMORE
, "No more operations allowed"}, /* not sure */
7080 {WSAECANCELLED
, "Operation cancelled"}, /* not sure */
7081 {WSAEINVALIDPROCTABLE
, "Invalid procedure table from service provider"},
7082 {WSAEINVALIDPROVIDER
, "Invalid service provider version number"},
7083 {WSAEPROVIDERFAILEDINIT
, "Unable to initialize a service provider"},
7084 {WSASYSCALLFAILURE
, "System call failure"},
7085 {WSASERVICE_NOT_FOUND
, "Service not found"}, /* not sure */
7086 {WSATYPE_NOT_FOUND
, "Class type not found"},
7087 {WSA_E_NO_MORE
, "No more resources available"}, /* really not sure */
7088 {WSA_E_CANCELLED
, "Operation already cancelled"}, /* really not sure */
7089 {WSAEREFUSED
, "Operation refused"}, /* not sure */
7092 {WSAHOST_NOT_FOUND
, "Host not found"},
7093 {WSATRY_AGAIN
, "Authoritative host not found during name lookup"},
7094 {WSANO_RECOVERY
, "Non-recoverable error during name lookup"},
7095 {WSANO_DATA
, "Valid name, no data record of requested type"},
7101 sys_strerror (int error_no
)
7104 static char unknown_msg
[40];
7106 if (error_no
>= 0 && error_no
< sys_nerr
)
7107 return sys_errlist
[error_no
];
7109 for (i
= 0; _wsa_errlist
[i
].errnum
>= 0; i
++)
7110 if (_wsa_errlist
[i
].errnum
== error_no
)
7111 return _wsa_errlist
[i
].msg
;
7113 sprintf (unknown_msg
, "Unidentified error: %d", error_no
);
7117 /* [andrewi 3-May-96] I've had conflicting results using both methods,
7118 but I believe the method of keeping the socket handle separate (and
7119 insuring it is not inheritable) is the correct one. */
7121 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7123 static int socket_to_fd (SOCKET s
);
7126 sys_socket (int af
, int type
, int protocol
)
7130 if (winsock_lib
== NULL
)
7133 return INVALID_SOCKET
;
7138 /* call the real socket function */
7139 s
= pfn_socket (af
, type
, protocol
);
7141 if (s
!= INVALID_SOCKET
)
7142 return socket_to_fd (s
);
7148 /* Convert a SOCKET to a file descriptor. */
7150 socket_to_fd (SOCKET s
)
7155 /* Although under NT 3.5 _open_osfhandle will accept a socket
7156 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
7157 that does not work under NT 3.1. However, we can get the same
7158 effect by using a backdoor function to replace an existing
7159 descriptor handle with the one we want. */
7161 /* allocate a file descriptor (with appropriate flags) */
7162 fd
= _open ("NUL:", _O_RDWR
);
7165 /* Make a non-inheritable copy of the socket handle. Note
7166 that it is possible that sockets aren't actually kernel
7167 handles, which appears to be the case on Windows 9x when
7168 the MS Proxy winsock client is installed. */
7170 /* Apparently there is a bug in NT 3.51 with some service
7171 packs, which prevents using DuplicateHandle to make a
7172 socket handle non-inheritable (causes WSACleanup to
7173 hang). The work-around is to use SetHandleInformation
7174 instead if it is available and implemented. */
7175 if (pfn_SetHandleInformation
)
7177 pfn_SetHandleInformation ((HANDLE
) s
, HANDLE_FLAG_INHERIT
, 0);
7181 HANDLE parent
= GetCurrentProcess ();
7182 HANDLE new_s
= INVALID_HANDLE_VALUE
;
7184 if (DuplicateHandle (parent
,
7190 DUPLICATE_SAME_ACCESS
))
7192 /* It is possible that DuplicateHandle succeeds even
7193 though the socket wasn't really a kernel handle,
7194 because a real handle has the same value. So
7195 test whether the new handle really is a socket. */
7196 long nonblocking
= 0;
7197 if (pfn_ioctlsocket ((SOCKET
) new_s
, FIONBIO
, &nonblocking
) == 0)
7199 pfn_closesocket (s
);
7204 CloseHandle (new_s
);
7209 eassert (fd
< MAXDESC
);
7210 fd_info
[fd
].hnd
= (HANDLE
) s
;
7212 /* set our own internal flags */
7213 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
7219 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7221 /* attach child_process to fd_info */
7222 if (fd_info
[ fd
].cp
!= NULL
)
7224 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
7228 fd_info
[ fd
].cp
= cp
;
7231 winsock_inuse
++; /* count open sockets */
7239 pfn_closesocket (s
);
7245 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
7247 if (winsock_lib
== NULL
)
7250 return SOCKET_ERROR
;
7254 if (fd_info
[s
].flags
& FILE_SOCKET
)
7256 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
7257 if (rc
== SOCKET_ERROR
)
7262 return SOCKET_ERROR
;
7266 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
7268 if (winsock_lib
== NULL
)
7271 return SOCKET_ERROR
;
7275 if (fd_info
[s
].flags
& FILE_SOCKET
)
7277 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
7278 if (rc
== SOCKET_ERROR
)
7283 return SOCKET_ERROR
;
7287 sys_htons (u_short hostshort
)
7289 return (winsock_lib
!= NULL
) ?
7290 pfn_htons (hostshort
) : hostshort
;
7294 sys_ntohs (u_short netshort
)
7296 return (winsock_lib
!= NULL
) ?
7297 pfn_ntohs (netshort
) : netshort
;
7301 sys_inet_addr (const char * cp
)
7303 return (winsock_lib
!= NULL
) ?
7304 pfn_inet_addr (cp
) : INADDR_NONE
;
7308 sys_gethostname (char * name
, int namelen
)
7310 if (winsock_lib
!= NULL
)
7315 retval
= pfn_gethostname (name
, namelen
);
7316 if (retval
== SOCKET_ERROR
)
7321 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
7322 return !GetComputerName (name
, (DWORD
*)&namelen
);
7325 return SOCKET_ERROR
;
7329 sys_gethostbyname (const char * name
)
7331 struct hostent
* host
;
7332 int h_err
= h_errno
;
7334 if (winsock_lib
== NULL
)
7336 h_errno
= NO_RECOVERY
;
7342 host
= pfn_gethostbyname (name
);
7354 sys_getservbyname (const char * name
, const char * proto
)
7356 struct servent
* serv
;
7358 if (winsock_lib
== NULL
)
7365 serv
= pfn_getservbyname (name
, proto
);
7372 sys_getpeername (int s
, struct sockaddr
*addr
, int * namelen
)
7374 if (winsock_lib
== NULL
)
7377 return SOCKET_ERROR
;
7381 if (fd_info
[s
].flags
& FILE_SOCKET
)
7383 int rc
= pfn_getpeername (SOCK_HANDLE (s
), addr
, namelen
);
7384 if (rc
== SOCKET_ERROR
)
7389 return SOCKET_ERROR
;
7393 sys_shutdown (int s
, int how
)
7395 if (winsock_lib
== NULL
)
7398 return SOCKET_ERROR
;
7402 if (fd_info
[s
].flags
& FILE_SOCKET
)
7404 int rc
= pfn_shutdown (SOCK_HANDLE (s
), how
);
7405 if (rc
== SOCKET_ERROR
)
7410 return SOCKET_ERROR
;
7414 sys_setsockopt (int s
, int level
, int optname
, const void * optval
, int optlen
)
7416 if (winsock_lib
== NULL
)
7419 return SOCKET_ERROR
;
7423 if (fd_info
[s
].flags
& FILE_SOCKET
)
7425 int rc
= pfn_setsockopt (SOCK_HANDLE (s
), level
, optname
,
7426 (const char *)optval
, optlen
);
7427 if (rc
== SOCKET_ERROR
)
7432 return SOCKET_ERROR
;
7436 sys_listen (int s
, int backlog
)
7438 if (winsock_lib
== NULL
)
7441 return SOCKET_ERROR
;
7445 if (fd_info
[s
].flags
& FILE_SOCKET
)
7447 int rc
= pfn_listen (SOCK_HANDLE (s
), backlog
);
7448 if (rc
== SOCKET_ERROR
)
7451 fd_info
[s
].flags
|= FILE_LISTEN
;
7455 return SOCKET_ERROR
;
7459 sys_getsockname (int s
, struct sockaddr
* name
, int * namelen
)
7461 if (winsock_lib
== NULL
)
7464 return SOCKET_ERROR
;
7468 if (fd_info
[s
].flags
& FILE_SOCKET
)
7470 int rc
= pfn_getsockname (SOCK_HANDLE (s
), name
, namelen
);
7471 if (rc
== SOCKET_ERROR
)
7476 return SOCKET_ERROR
;
7480 sys_accept (int s
, struct sockaddr
* addr
, int * addrlen
)
7482 if (winsock_lib
== NULL
)
7489 if (fd_info
[s
].flags
& FILE_LISTEN
)
7491 SOCKET t
= pfn_accept (SOCK_HANDLE (s
), addr
, addrlen
);
7493 if (t
== INVALID_SOCKET
)
7496 fd
= socket_to_fd (t
);
7500 fd_info
[s
].cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7501 ResetEvent (fd_info
[s
].cp
->char_avail
);
7510 sys_recvfrom (int s
, char * buf
, int len
, int flags
,
7511 struct sockaddr
* from
, int * fromlen
)
7513 if (winsock_lib
== NULL
)
7516 return SOCKET_ERROR
;
7520 if (fd_info
[s
].flags
& FILE_SOCKET
)
7522 int rc
= pfn_recvfrom (SOCK_HANDLE (s
), buf
, len
, flags
, from
, fromlen
);
7523 if (rc
== SOCKET_ERROR
)
7528 return SOCKET_ERROR
;
7532 sys_sendto (int s
, const char * buf
, int len
, int flags
,
7533 const struct sockaddr
* to
, int tolen
)
7535 if (winsock_lib
== NULL
)
7538 return SOCKET_ERROR
;
7542 if (fd_info
[s
].flags
& FILE_SOCKET
)
7544 int rc
= pfn_sendto (SOCK_HANDLE (s
), buf
, len
, flags
, to
, tolen
);
7545 if (rc
== SOCKET_ERROR
)
7550 return SOCKET_ERROR
;
7553 /* Windows does not have an fcntl function. Provide an implementation
7554 good enough for Emacs. */
7556 fcntl (int s
, int cmd
, int options
)
7558 /* In the w32 Emacs port, fcntl (fd, F_DUPFD_CLOEXEC, fd1) is always
7559 invoked in a context where fd1 is closed and all descriptors less
7560 than fd1 are open, so sys_dup is an adequate implementation. */
7561 if (cmd
== F_DUPFD_CLOEXEC
)
7564 if (winsock_lib
== NULL
)
7571 if (fd_info
[s
].flags
& FILE_SOCKET
)
7573 if (cmd
== F_SETFL
&& options
== O_NONBLOCK
)
7575 unsigned long nblock
= 1;
7576 int rc
= pfn_ioctlsocket (SOCK_HANDLE (s
), FIONBIO
, &nblock
);
7577 if (rc
== SOCKET_ERROR
)
7579 /* Keep track of the fact that we set this to non-blocking. */
7580 fd_info
[s
].flags
|= FILE_NDELAY
;
7586 return SOCKET_ERROR
;
7590 return SOCKET_ERROR
;
7594 /* Shadow main io functions: we need to handle pipes and sockets more
7595 intelligently, and implement non-blocking mode as well. */
7608 if (fd
< MAXDESC
&& fd_info
[fd
].cp
)
7610 child_process
* cp
= fd_info
[fd
].cp
;
7612 fd_info
[fd
].cp
= NULL
;
7614 if (CHILD_ACTIVE (cp
))
7616 /* if last descriptor to active child_process then cleanup */
7618 for (i
= 0; i
< MAXDESC
; i
++)
7622 if (fd_info
[i
].cp
== cp
)
7627 if (fd_info
[fd
].flags
& FILE_SOCKET
)
7629 if (winsock_lib
== NULL
) emacs_abort ();
7631 pfn_shutdown (SOCK_HANDLE (fd
), 2);
7632 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
7634 winsock_inuse
--; /* count open sockets */
7636 /* If the process handle is NULL, it's either a socket
7637 or serial connection, or a subprocess that was
7638 already reaped by reap_subprocess, but whose
7639 resources were not yet freed, because its output was
7640 not fully read yet by the time it was reaped. (This
7641 usually happens with async subprocesses whose output
7642 is being read by Emacs.) Otherwise, this process was
7643 not reaped yet, so we set its FD to a negative value
7644 to make sure sys_select will eventually get to
7645 calling the SIGCHLD handler for it, which will then
7646 invoke waitpid and reap_subprocess. */
7647 if (cp
->procinfo
.hProcess
== NULL
)
7655 if (fd
>= 0 && fd
< MAXDESC
)
7656 fd_info
[fd
].flags
= 0;
7658 /* Note that sockets do not need special treatment here (at least on
7659 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
7660 closesocket is equivalent to CloseHandle, which is to be expected
7661 because socket handles are fully fledged kernel handles. */
7673 if (new_fd
>= 0 && new_fd
< MAXDESC
)
7675 /* duplicate our internal info as well */
7676 fd_info
[new_fd
] = fd_info
[fd
];
7682 sys_dup2 (int src
, int dst
)
7686 if (dst
< 0 || dst
>= MAXDESC
)
7692 /* make sure we close the destination first if it's a pipe or socket */
7693 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
7696 rc
= _dup2 (src
, dst
);
7699 /* duplicate our internal info as well */
7700 fd_info
[dst
] = fd_info
[src
];
7706 pipe2 (int * phandles
, int pipe2_flags
)
7711 eassert (pipe2_flags
== O_CLOEXEC
);
7713 /* make pipe handles non-inheritable; when we spawn a child, we
7714 replace the relevant handle with an inheritable one. Also put
7715 pipes into binary mode; we will do text mode translation ourselves
7717 rc
= _pipe (phandles
, 0, _O_NOINHERIT
| _O_BINARY
);
7721 /* Protect against overflow, since Windows can open more handles than
7722 our fd_info array has room for. */
7723 if (phandles
[0] >= MAXDESC
|| phandles
[1] >= MAXDESC
)
7725 _close (phandles
[0]);
7726 _close (phandles
[1]);
7732 flags
= FILE_PIPE
| FILE_READ
| FILE_BINARY
;
7733 fd_info
[phandles
[0]].flags
= flags
;
7735 flags
= FILE_PIPE
| FILE_WRITE
| FILE_BINARY
;
7736 fd_info
[phandles
[1]].flags
= flags
;
7743 /* Function to do blocking read of one byte, needed to implement
7744 select. It is only allowed on communication ports, sockets, or
7747 _sys_read_ahead (int fd
)
7752 if (fd
< 0 || fd
>= MAXDESC
)
7753 return STATUS_READ_ERROR
;
7755 cp
= fd_info
[fd
].cp
;
7757 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7758 return STATUS_READ_ERROR
;
7760 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SERIAL
| FILE_SOCKET
)) == 0
7761 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
7763 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd
));
7767 cp
->status
= STATUS_READ_IN_PROGRESS
;
7769 if (fd_info
[fd
].flags
& FILE_PIPE
)
7771 rc
= _read (fd
, &cp
->chr
, sizeof (char));
7773 /* Give subprocess time to buffer some more output for us before
7774 reporting that input is available; we need this because Windows 95
7775 connects DOS programs to pipes by making the pipe appear to be
7776 the normal console stdout - as a result most DOS programs will
7777 write to stdout without buffering, ie. one character at a
7778 time. Even some W32 programs do this - "dir" in a command
7779 shell on NT is very slow if we don't do this. */
7782 int wait
= w32_pipe_read_delay
;
7788 /* Yield remainder of our time slice, effectively giving a
7789 temporary priority boost to the child process. */
7793 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7795 HANDLE hnd
= fd_info
[fd
].hnd
;
7796 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7799 /* Configure timeouts for blocking read. */
7800 if (!GetCommTimeouts (hnd
, &ct
))
7802 cp
->status
= STATUS_READ_ERROR
;
7803 return STATUS_READ_ERROR
;
7805 ct
.ReadIntervalTimeout
= 0;
7806 ct
.ReadTotalTimeoutMultiplier
= 0;
7807 ct
.ReadTotalTimeoutConstant
= 0;
7808 if (!SetCommTimeouts (hnd
, &ct
))
7810 cp
->status
= STATUS_READ_ERROR
;
7811 return STATUS_READ_ERROR
;
7814 if (!ReadFile (hnd
, &cp
->chr
, sizeof (char), (DWORD
*) &rc
, ovl
))
7816 if (GetLastError () != ERROR_IO_PENDING
)
7818 cp
->status
= STATUS_READ_ERROR
;
7819 return STATUS_READ_ERROR
;
7821 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
7823 cp
->status
= STATUS_READ_ERROR
;
7824 return STATUS_READ_ERROR
;
7828 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
7830 unsigned long nblock
= 0;
7831 /* We always want this to block, so temporarily disable NDELAY. */
7832 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7833 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7835 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
7837 if (fd_info
[fd
].flags
& FILE_NDELAY
)
7840 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
7844 if (rc
== sizeof (char))
7845 cp
->status
= STATUS_READ_SUCCEEDED
;
7847 cp
->status
= STATUS_READ_FAILED
;
7853 _sys_wait_accept (int fd
)
7859 if (fd
< 0 || fd
>= MAXDESC
)
7860 return STATUS_READ_ERROR
;
7862 cp
= fd_info
[fd
].cp
;
7864 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
7865 return STATUS_READ_ERROR
;
7867 cp
->status
= STATUS_READ_FAILED
;
7869 hEv
= pfn_WSACreateEvent ();
7870 rc
= pfn_WSAEventSelect (SOCK_HANDLE (fd
), hEv
, FD_ACCEPT
);
7871 if (rc
!= SOCKET_ERROR
)
7874 rc
= WaitForSingleObject (hEv
, 500);
7876 } while (rc
== WAIT_TIMEOUT
7877 && cp
->status
!= STATUS_READ_ERROR
7879 pfn_WSAEventSelect (SOCK_HANDLE (fd
), NULL
, 0);
7880 if (rc
== WAIT_OBJECT_0
)
7881 cp
->status
= STATUS_READ_SUCCEEDED
;
7883 pfn_WSACloseEvent (hEv
);
7889 sys_read (int fd
, char * buffer
, unsigned int count
)
7894 char * orig_buffer
= buffer
;
7902 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
7904 child_process
*cp
= fd_info
[fd
].cp
;
7906 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
7914 /* re-read CR carried over from last read */
7915 if (fd_info
[fd
].flags
& FILE_LAST_CR
)
7917 if (fd_info
[fd
].flags
& FILE_BINARY
) emacs_abort ();
7921 fd_info
[fd
].flags
&= ~FILE_LAST_CR
;
7924 /* presence of a child_process structure means we are operating in
7925 non-blocking mode - otherwise we just call _read directly.
7926 Note that the child_process structure might be missing because
7927 reap_subprocess has been called; in this case the pipe is
7928 already broken, so calling _read on it is okay. */
7931 int current_status
= cp
->status
;
7933 switch (current_status
)
7935 case STATUS_READ_FAILED
:
7936 case STATUS_READ_ERROR
:
7937 /* report normal EOF if nothing in buffer */
7939 fd_info
[fd
].flags
|= FILE_AT_EOF
;
7942 case STATUS_READ_READY
:
7943 case STATUS_READ_IN_PROGRESS
:
7944 DebPrint (("sys_read called when read is in progress\n"));
7945 errno
= EWOULDBLOCK
;
7948 case STATUS_READ_SUCCEEDED
:
7949 /* consume read-ahead char */
7950 *buffer
++ = cp
->chr
;
7953 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
7954 ResetEvent (cp
->char_avail
);
7956 case STATUS_READ_ACKNOWLEDGED
:
7960 DebPrint (("sys_read: bad status %d\n", current_status
));
7965 if (fd_info
[fd
].flags
& FILE_PIPE
)
7967 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
7968 to_read
= min (waiting
, (DWORD
) count
);
7971 nchars
+= _read (fd
, buffer
, to_read
);
7973 else if (fd_info
[fd
].flags
& FILE_SERIAL
)
7975 HANDLE hnd
= fd_info
[fd
].hnd
;
7976 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_read
;
7982 /* Configure timeouts for non-blocking read. */
7983 if (!GetCommTimeouts (hnd
, &ct
))
7988 ct
.ReadIntervalTimeout
= MAXDWORD
;
7989 ct
.ReadTotalTimeoutMultiplier
= 0;
7990 ct
.ReadTotalTimeoutConstant
= 0;
7991 if (!SetCommTimeouts (hnd
, &ct
))
7997 if (!ResetEvent (ovl
->hEvent
))
8002 if (!ReadFile (hnd
, buffer
, count
, (DWORD
*) &rc
, ovl
))
8004 if (GetLastError () != ERROR_IO_PENDING
)
8009 if (!GetOverlappedResult (hnd
, ovl
, (DWORD
*) &rc
, TRUE
))
8018 else /* FILE_SOCKET */
8020 if (winsock_lib
== NULL
) emacs_abort ();
8022 /* do the equivalent of a non-blocking read */
8023 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
8024 if (waiting
== 0 && nchars
== 0)
8026 errno
= EWOULDBLOCK
;
8032 /* always use binary mode for sockets */
8033 int res
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
8034 if (res
== SOCKET_ERROR
)
8036 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
8037 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8047 int nread
= _read (fd
, buffer
, count
);
8050 else if (nchars
== 0)
8055 fd_info
[fd
].flags
|= FILE_AT_EOF
;
8056 /* Perform text mode translation if required. */
8057 else if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8059 nchars
= crlf_to_lf (nchars
, orig_buffer
);
8060 /* If buffer contains only CR, return that. To be absolutely
8061 sure we should attempt to read the next char, but in
8062 practice a CR to be followed by LF would not appear by
8063 itself in the buffer. */
8064 if (nchars
> 1 && orig_buffer
[nchars
- 1] == 0x0d)
8066 fd_info
[fd
].flags
|= FILE_LAST_CR
;
8072 nchars
= _read (fd
, buffer
, count
);
8077 /* From w32xfns.c */
8078 extern HANDLE interrupt_handle
;
8080 /* For now, don't bother with a non-blocking mode */
8082 sys_write (int fd
, const void * buffer
, unsigned int count
)
8092 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
| FILE_SERIAL
))
8094 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
8100 /* Perform text mode translation if required. */
8101 if ((fd_info
[fd
].flags
& FILE_BINARY
) == 0)
8103 char * tmpbuf
= alloca (count
* 2);
8104 unsigned char * src
= (void *)buffer
;
8105 unsigned char * dst
= tmpbuf
;
8110 unsigned char *next
;
8111 /* copy next line or remaining bytes */
8112 next
= _memccpy (dst
, src
, '\n', nbytes
);
8115 /* copied one line ending with '\n' */
8116 int copied
= next
- dst
;
8119 /* insert '\r' before '\n' */
8126 /* copied remaining partial line -> now finished */
8133 if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SERIAL
)
8135 HANDLE hnd
= (HANDLE
) _get_osfhandle (fd
);
8136 OVERLAPPED
*ovl
= &fd_info
[fd
].cp
->ovl_write
;
8137 HANDLE wait_hnd
[2] = { interrupt_handle
, ovl
->hEvent
};
8140 if (!WriteFile (hnd
, buffer
, count
, (DWORD
*) &nchars
, ovl
))
8142 if (GetLastError () != ERROR_IO_PENDING
)
8147 if (detect_input_pending ())
8148 active
= MsgWaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
,
8151 active
= WaitForMultipleObjects (2, wait_hnd
, FALSE
, INFINITE
);
8152 if (active
== WAIT_OBJECT_0
)
8153 { /* User pressed C-g, cancel write, then leave. Don't bother
8154 cleaning up as we may only get stuck in buggy drivers. */
8155 PurgeComm (hnd
, PURGE_TXABORT
| PURGE_TXCLEAR
);
8160 if (active
== WAIT_OBJECT_0
+ 1
8161 && !GetOverlappedResult (hnd
, ovl
, (DWORD
*) &nchars
, TRUE
))
8168 else if (fd
< MAXDESC
&& fd_info
[fd
].flags
& FILE_SOCKET
)
8170 unsigned long nblock
= 0;
8171 if (winsock_lib
== NULL
) emacs_abort ();
8173 /* TODO: implement select() properly so non-blocking I/O works. */
8174 /* For now, make sure the write blocks. */
8175 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8176 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8178 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
8180 /* Set the socket back to non-blocking if it was before,
8181 for other operations that support it. */
8182 if (fd_info
[fd
].flags
& FILE_NDELAY
)
8185 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONBIO
, &nblock
);
8188 if (nchars
== SOCKET_ERROR
)
8190 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
8191 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
8197 /* Some networked filesystems don't like too large writes, so
8198 break them into smaller chunks. See the Comments section of
8199 the MSDN documentation of WriteFile for details behind the
8200 choice of the value of CHUNK below. See also the thread
8201 http://thread.gmane.org/gmane.comp.version-control.git/145294
8202 in the git mailing list. */
8203 const unsigned char *p
= buffer
;
8204 const unsigned chunk
= 30 * 1024 * 1024;
8209 unsigned this_chunk
= count
< chunk
? count
: chunk
;
8210 int n
= _write (fd
, p
, this_chunk
);
8218 else if (n
< this_chunk
)
8229 /* Emulation of SIOCGIFCONF and getifaddrs, see process.c. */
8231 extern Lisp_Object
conv_sockaddr_to_lisp (struct sockaddr
*, int);
8233 /* Return information about network interface IFNAME, or about all
8234 interfaces (if IFNAME is nil). */
8236 network_interface_get_info (Lisp_Object ifname
)
8238 ULONG ainfo_len
= sizeof (IP_ADAPTER_INFO
);
8239 IP_ADAPTER_INFO
*adapter
, *ainfo
= xmalloc (ainfo_len
);
8240 DWORD retval
= get_adapters_info (ainfo
, &ainfo_len
);
8241 Lisp_Object res
= Qnil
;
8243 if (retval
== ERROR_BUFFER_OVERFLOW
)
8245 ainfo
= xrealloc (ainfo
, ainfo_len
);
8246 retval
= get_adapters_info (ainfo
, &ainfo_len
);
8249 if (retval
== ERROR_SUCCESS
)
8251 int eth_count
= 0, tr_count
= 0, fddi_count
= 0, ppp_count
= 0;
8252 int sl_count
= 0, wlan_count
= 0, lo_count
= 0, ifx_count
= 0;
8254 struct sockaddr_in sa
;
8256 /* For the below, we need some winsock functions, so make sure
8257 the winsock DLL is loaded. If we cannot successfully load
8258 it, they will have no use of the information we provide,
8260 if (!winsock_lib
&& !init_winsock (1))
8263 for (adapter
= ainfo
; adapter
; adapter
= adapter
->Next
)
8265 char namebuf
[MAX_ADAPTER_NAME_LENGTH
+ 4];
8267 /* Present Unix-compatible interface names, instead of the
8268 Windows names, which are really GUIDs not readable by
8270 static const char *ifmt
[] = {
8271 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
8286 switch (adapter
->Type
)
8288 case MIB_IF_TYPE_ETHERNET
:
8289 /* Windows before Vista reports wireless adapters as
8290 Ethernet. Work around by looking at the Description
8292 if (strstr (adapter
->Description
, "Wireless "))
8295 if_num
= wlan_count
++;
8299 ifmt_idx
= ETHERNET
;
8300 if_num
= eth_count
++;
8303 case MIB_IF_TYPE_TOKENRING
:
8304 ifmt_idx
= TOKENRING
;
8305 if_num
= tr_count
++;
8307 case MIB_IF_TYPE_FDDI
:
8309 if_num
= fddi_count
++;
8311 case MIB_IF_TYPE_PPP
:
8313 if_num
= ppp_count
++;
8315 case MIB_IF_TYPE_SLIP
:
8317 if_num
= sl_count
++;
8319 case IF_TYPE_IEEE80211
:
8321 if_num
= wlan_count
++;
8323 case MIB_IF_TYPE_LOOPBACK
:
8326 ifmt_idx
= LOOPBACK
;
8327 if_num
= lo_count
++;
8333 ifmt_idx
= OTHER_IF
;
8334 if_num
= ifx_count
++;
8337 if (ifmt_idx
== NONE
)
8339 sprintf (namebuf
, ifmt
[ifmt_idx
], if_num
);
8341 sa
.sin_family
= AF_INET
;
8342 ip_addr
= sys_inet_addr (adapter
->IpAddressList
.IpAddress
.String
);
8343 if (ip_addr
== INADDR_NONE
)
8345 /* Bogus address, skip this interface. */
8348 sa
.sin_addr
.s_addr
= ip_addr
;
8351 res
= Fcons (Fcons (build_string (namebuf
),
8352 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8353 sizeof (struct sockaddr
))),
8355 else if (strcmp (namebuf
, SSDATA (ifname
)) == 0)
8357 Lisp_Object hwaddr
= Fmake_vector (make_number (6), Qnil
);
8358 register struct Lisp_Vector
*p
= XVECTOR (hwaddr
);
8359 Lisp_Object flags
= Qnil
;
8363 /* Flags. We guess most of them by type, since the
8364 Windows flags are different and hard to get by. */
8365 flags
= Fcons (intern ("up"), flags
);
8366 if (ifmt_idx
== ETHERNET
|| ifmt_idx
== WLAN
)
8368 flags
= Fcons (intern ("broadcast"), flags
);
8369 flags
= Fcons (intern ("multicast"), flags
);
8371 flags
= Fcons (intern ("running"), flags
);
8372 if (ifmt_idx
== PPP
)
8374 flags
= Fcons (intern ("pointopoint"), flags
);
8375 flags
= Fcons (intern ("noarp"), flags
);
8377 if (adapter
->HaveWins
)
8378 flags
= Fcons (intern ("WINS"), flags
);
8379 if (adapter
->DhcpEnabled
)
8380 flags
= Fcons (intern ("dynamic"), flags
);
8382 res
= Fcons (flags
, res
);
8384 /* Hardware address and its family. */
8385 for (n
= 0; n
< adapter
->AddressLength
; n
++)
8386 p
->contents
[n
] = make_number ((int) adapter
->Address
[n
]);
8387 /* Windows does not support AF_LINK or AF_PACKET family
8388 of addresses. Use an arbitrary family number that is
8389 identical to what GNU/Linux returns. */
8390 res
= Fcons (Fcons (make_number (1), hwaddr
), res
);
8393 sa
.sin_family
= AF_INET
;
8394 net_mask
= sys_inet_addr (adapter
->IpAddressList
.IpMask
.String
);
8395 if (net_mask
!= INADDR_NONE
)
8397 sa
.sin_addr
.s_addr
= net_mask
;
8399 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8400 sizeof (struct sockaddr
)),
8404 res
= Fcons (Qnil
, res
);
8406 sa
.sin_family
= AF_INET
;
8407 if (ip_addr
!= INADDR_NONE
)
8409 /* Broadcast address is only reported by
8410 GetAdaptersAddresses, which is of limited
8411 availability. Generate it on our own. */
8412 u_long bcast_addr
= (ip_addr
& net_mask
) | ~net_mask
;
8414 sa
.sin_addr
.s_addr
= bcast_addr
;
8416 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8417 sizeof (struct sockaddr
)),
8421 sa
.sin_addr
.s_addr
= ip_addr
;
8423 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8424 sizeof (struct sockaddr
)),
8428 res
= Fcons (Qnil
, Fcons (Qnil
, res
));
8431 /* GetAdaptersInfo is documented to not report loopback
8432 interfaces, so we generate one out of thin air. */
8435 sa
.sin_family
= AF_INET
;
8439 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8440 res
= Fcons (Fcons (build_string ("lo"),
8441 conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8442 sizeof (struct sockaddr
))),
8445 else if (strcmp (SSDATA (ifname
), "lo") == 0)
8447 res
= Fcons (Fcons (intern ("running"),
8448 Fcons (intern ("loopback"),
8449 Fcons (intern ("up"), Qnil
))), Qnil
);
8450 /* 772 is what 3 different GNU/Linux systems report for
8451 the loopback interface. */
8452 res
= Fcons (Fcons (make_number (772),
8453 Fmake_vector (make_number (6),
8456 sa
.sin_addr
.s_addr
= sys_inet_addr ("255.0.0.0");
8457 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8458 sizeof (struct sockaddr
)),
8460 sa
.sin_addr
.s_addr
= sys_inet_addr ("0.0.0.0");
8461 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8462 sizeof (struct sockaddr
)),
8464 sa
.sin_addr
.s_addr
= sys_inet_addr ("127.0.0.1");
8465 res
= Fcons (conv_sockaddr_to_lisp ((struct sockaddr
*) &sa
,
8466 sizeof (struct sockaddr
)),
8479 network_interface_list (void)
8481 return network_interface_get_info (Qnil
);
8485 network_interface_info (Lisp_Object ifname
)
8487 return network_interface_get_info (ifname
);
8491 /* The Windows CRT functions are "optimized for speed", so they don't
8492 check for timezone and DST changes if they were last called less
8493 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
8494 all Emacs features that repeatedly call time functions (e.g.,
8495 display-time) are in real danger of missing timezone and DST
8496 changes. Calling tzset before each localtime call fixes that. */
8498 sys_localtime (const time_t *t
)
8501 return localtime (t
);
8506 /* Try loading LIBRARY_ID from the file(s) specified in
8507 Vdynamic_library_alist. If the library is loaded successfully,
8508 return the handle of the DLL, and record the filename in the
8509 property :loaded-from of LIBRARY_ID. If the library could not be
8510 found, or when it was already loaded (because the handle is not
8511 recorded anywhere, and so is lost after use), return NULL.
8513 We could also save the handle in :loaded-from, but currently
8514 there's no use case for it. */
8516 w32_delayed_load (Lisp_Object library_id
)
8518 HMODULE dll_handle
= NULL
;
8520 CHECK_SYMBOL (library_id
);
8522 if (CONSP (Vdynamic_library_alist
)
8523 && NILP (Fassq (library_id
, Vlibrary_cache
)))
8525 Lisp_Object found
= Qnil
;
8526 Lisp_Object dlls
= Fassq (library_id
, Vdynamic_library_alist
);
8529 for (dlls
= XCDR (dlls
); CONSP (dlls
); dlls
= XCDR (dlls
))
8531 Lisp_Object dll
= XCAR (dlls
);
8532 char name
[MAX_UTF8_PATH
];
8536 dll
= ENCODE_FILE (dll
);
8537 if (w32_unicode_filenames
)
8539 wchar_t name_w
[MAX_PATH
];
8541 filename_to_utf16 (SSDATA (dll
), name_w
);
8542 dll_handle
= LoadLibraryW (name_w
);
8545 res
= GetModuleFileNameW (dll_handle
, name_w
,
8548 filename_from_utf16 (name_w
, name
);
8553 char name_a
[MAX_PATH
];
8555 filename_to_ansi (SSDATA (dll
), name_a
);
8556 dll_handle
= LoadLibraryA (name_a
);
8559 res
= GetModuleFileNameA (dll_handle
, name_a
,
8562 filename_from_ansi (name_a
, name
);
8567 ptrdiff_t len
= strlen (name
);
8570 /* Possibly truncated */
8571 ? make_specified_string (name
, -1, len
, 1)
8577 Fput (library_id
, QCloaded_from
, found
);
8585 check_windows_init_file (void)
8587 /* A common indication that Emacs is not installed properly is when
8588 it cannot find the Windows installation file. If this file does
8589 not exist in the expected place, tell the user. */
8591 if (!noninteractive
&& !inhibit_window_system
8592 /* Vload_path is not yet initialized when we are loading
8594 && NILP (Vpurify_flag
))
8596 Lisp_Object init_file
;
8599 /* Implementation note: this function runs early during Emacs
8600 startup, before startup.el is run. So Vload_path is still in
8601 its initial unibyte form, but it holds UTF-8 encoded file
8602 names, since init_callproc was already called. So we do not
8603 need to ENCODE_FILE here, but we do need to convert the file
8604 names from UTF-8 to ANSI. */
8605 init_file
= build_string ("term/w32-win");
8606 fd
= openp (Vload_path
, init_file
, Fget_load_suffixes (), NULL
, Qnil
, 0);
8609 Lisp_Object load_path_print
= Fprin1_to_string (Vload_path
, Qnil
);
8610 char *init_file_name
= SDATA (init_file
);
8611 char *load_path
= SDATA (load_path_print
);
8612 char *buffer
= alloca (1024
8613 + strlen (init_file_name
)
8614 + strlen (load_path
));
8619 "The Emacs Windows initialization file \"%s.el\" "
8620 "could not be found in your Emacs installation. "
8621 "Emacs checked the following directories for this file:\n"
8623 "When Emacs cannot find this file, it usually means that it "
8624 "was not installed properly, or its distribution file was "
8625 "not unpacked properly.\nSee the README.W32 file in the "
8626 "top-level Emacs directory for more information.",
8627 init_file_name
, load_path
);
8628 needed
= MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
,
8632 wchar_t *msg_w
= alloca ((needed
+ 1) * sizeof (wchar_t));
8634 MultiByteToWideChar (CP_UTF8
, MB_ERR_INVALID_CHARS
, buffer
, -1,
8636 needed
= WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1,
8637 NULL
, 0, NULL
, NULL
);
8640 char *msg_a
= alloca (needed
+ 1);
8642 WideCharToMultiByte (CP_ACP
, 0, msg_w
, -1, msg_a
, needed
,
8649 "Emacs Abort Dialog",
8650 MB_OK
| MB_ICONEXCLAMATION
| MB_TASKMODAL
);
8651 /* Use the low-level system abort. */
8662 term_ntproc (int ignored
)
8668 /* shutdown the socket interface if necessary */
8675 init_ntproc (int dumping
)
8677 sigset_t initial_mask
= 0;
8679 /* Initialize the socket interface now if available and requested by
8680 the user by defining PRELOAD_WINSOCK; otherwise loading will be
8681 delayed until open-network-stream is called (w32-has-winsock can
8682 also be used to dynamically load or reload winsock).
8684 Conveniently, init_environment is called before us, so
8685 PRELOAD_WINSOCK can be set in the registry. */
8687 /* Always initialize this correctly. */
8690 if (getenv ("PRELOAD_WINSOCK") != NULL
)
8691 init_winsock (TRUE
);
8693 /* Initial preparation for subprocess support: replace our standard
8694 handles with non-inheritable versions. */
8697 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
8698 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
8699 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
8701 parent
= GetCurrentProcess ();
8703 /* ignore errors when duplicating and closing; typically the
8704 handles will be invalid when running as a gui program. */
8705 DuplicateHandle (parent
,
8706 GetStdHandle (STD_INPUT_HANDLE
),
8711 DUPLICATE_SAME_ACCESS
);
8713 DuplicateHandle (parent
,
8714 GetStdHandle (STD_OUTPUT_HANDLE
),
8719 DUPLICATE_SAME_ACCESS
);
8721 DuplicateHandle (parent
,
8722 GetStdHandle (STD_ERROR_HANDLE
),
8727 DUPLICATE_SAME_ACCESS
);
8733 if (stdin_save
!= INVALID_HANDLE_VALUE
)
8734 _open_osfhandle ((intptr_t) stdin_save
, O_TEXT
);
8736 _open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
8739 if (stdout_save
!= INVALID_HANDLE_VALUE
)
8740 _open_osfhandle ((intptr_t) stdout_save
, O_TEXT
);
8742 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8745 if (stderr_save
!= INVALID_HANDLE_VALUE
)
8746 _open_osfhandle ((intptr_t) stderr_save
, O_TEXT
);
8748 _open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
8752 /* unfortunately, atexit depends on implementation of malloc */
8753 /* atexit (term_ntproc); */
8756 /* Make sure we start with all signals unblocked. */
8757 sigprocmask (SIG_SETMASK
, &initial_mask
, NULL
);
8758 signal (SIGABRT
, term_ntproc
);
8762 /* determine which drives are fixed, for GetCachedVolumeInformation */
8764 /* GetDriveType must have trailing backslash. */
8765 char drive
[] = "A:\\";
8767 /* Loop over all possible drive letters */
8768 while (*drive
<= 'Z')
8770 /* Record if this drive letter refers to a fixed drive. */
8771 fixed_drives
[DRIVE_INDEX (*drive
)] =
8772 (GetDriveType (drive
) == DRIVE_FIXED
);
8777 /* Reset the volume info cache. */
8778 volume_cache
= NULL
;
8783 shutdown_handler ensures that buffers' autosave files are
8784 up to date when the user logs off, or the system shuts down.
8787 shutdown_handler (DWORD type
)
8789 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
8790 if (type
== CTRL_CLOSE_EVENT
/* User closes console window. */
8791 || type
== CTRL_LOGOFF_EVENT
/* User logs off. */
8792 || type
== CTRL_SHUTDOWN_EVENT
) /* User shutsdown. */
8794 /* Shut down cleanly, making sure autosave files are up to date. */
8795 shut_down_emacs (0, Qnil
);
8798 /* Allow other handlers to handle this signal. */
8803 globals_of_w32 is used to initialize those global variables that
8804 must always be initialized on startup even when the global variable
8805 initialized is non zero (see the function main in emacs.c).
8808 globals_of_w32 (void)
8810 HMODULE kernel32
= GetModuleHandle ("kernel32.dll");
8812 get_process_times_fn
= (GetProcessTimes_Proc
)
8813 GetProcAddress (kernel32
, "GetProcessTimes");
8815 DEFSYM (QCloaded_from
, ":loaded-from");
8817 g_b_init_is_windows_9x
= 0;
8818 g_b_init_open_process_token
= 0;
8819 g_b_init_get_token_information
= 0;
8820 g_b_init_lookup_account_sid
= 0;
8821 g_b_init_get_sid_sub_authority
= 0;
8822 g_b_init_get_sid_sub_authority_count
= 0;
8823 g_b_init_get_security_info
= 0;
8824 g_b_init_get_file_security_w
= 0;
8825 g_b_init_get_file_security_a
= 0;
8826 g_b_init_get_security_descriptor_owner
= 0;
8827 g_b_init_get_security_descriptor_group
= 0;
8828 g_b_init_is_valid_sid
= 0;
8829 g_b_init_create_toolhelp32_snapshot
= 0;
8830 g_b_init_process32_first
= 0;
8831 g_b_init_process32_next
= 0;
8832 g_b_init_open_thread_token
= 0;
8833 g_b_init_impersonate_self
= 0;
8834 g_b_init_revert_to_self
= 0;
8835 g_b_init_get_process_memory_info
= 0;
8836 g_b_init_get_process_working_set_size
= 0;
8837 g_b_init_global_memory_status
= 0;
8838 g_b_init_global_memory_status_ex
= 0;
8839 g_b_init_equal_sid
= 0;
8840 g_b_init_copy_sid
= 0;
8841 g_b_init_get_length_sid
= 0;
8842 g_b_init_get_native_system_info
= 0;
8843 g_b_init_get_system_times
= 0;
8844 g_b_init_create_symbolic_link_w
= 0;
8845 g_b_init_create_symbolic_link_a
= 0;
8846 g_b_init_get_security_descriptor_dacl
= 0;
8847 g_b_init_convert_sd_to_sddl
= 0;
8848 g_b_init_convert_sddl_to_sd
= 0;
8849 g_b_init_is_valid_security_descriptor
= 0;
8850 g_b_init_set_file_security_w
= 0;
8851 g_b_init_set_file_security_a
= 0;
8852 g_b_init_get_adapters_info
= 0;
8853 num_of_processors
= 0;
8854 /* The following sets a handler for shutdown notifications for
8855 console apps. This actually applies to Emacs in both console and
8856 GUI modes, since we had to fool windows into thinking emacs is a
8857 console application to get console mode to work. */
8858 SetConsoleCtrlHandler (shutdown_handler
, TRUE
);
8860 /* "None" is the default group name on standalone workstations. */
8861 strcpy (dflt_group_name
, "None");
8863 /* Reset, in case it has some value inherited from dump time. */
8864 w32_stat_get_owner_group
= 0;
8866 /* If w32_unicode_filenames is non-zero, we will be using Unicode
8867 (a.k.a. "wide") APIs to invoke functions that accept file
8869 if (is_windows_9x ())
8870 w32_unicode_filenames
= 0;
8872 w32_unicode_filenames
= 1;
8875 /* For make-serial-process */
8877 serial_open (Lisp_Object port_obj
)
8879 char *port
= SSDATA (port_obj
);
8884 hnd
= CreateFile (port
, GENERIC_READ
| GENERIC_WRITE
, 0, 0,
8885 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, 0);
8886 if (hnd
== INVALID_HANDLE_VALUE
)
8887 error ("Could not open %s", port
);
8888 fd
= (int) _open_osfhandle ((intptr_t) hnd
, 0);
8890 error ("Could not open %s", port
);
8894 error ("Could not create child process");
8896 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
8897 fd_info
[ fd
].hnd
= hnd
;
8898 fd_info
[ fd
].flags
|=
8899 FILE_READ
| FILE_WRITE
| FILE_BINARY
| FILE_SERIAL
;
8900 if (fd_info
[ fd
].cp
!= NULL
)
8902 error ("fd_info[fd = %d] is already in use", fd
);
8904 fd_info
[ fd
].cp
= cp
;
8905 cp
->ovl_read
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8906 if (cp
->ovl_read
.hEvent
== NULL
)
8907 error ("Could not create read event");
8908 cp
->ovl_write
.hEvent
= CreateEvent (NULL
, TRUE
, FALSE
, NULL
);
8909 if (cp
->ovl_write
.hEvent
== NULL
)
8910 error ("Could not create write event");
8915 /* For serial-process-configure */
8917 serial_configure (struct Lisp_Process
*p
, Lisp_Object contact
)
8919 Lisp_Object childp2
= Qnil
;
8920 Lisp_Object tem
= Qnil
;
8924 char summary
[4] = "???"; /* This usually becomes "8N1". */
8926 if ((fd_info
[ p
->outfd
].flags
& FILE_SERIAL
) == 0)
8927 error ("Not a serial process");
8928 hnd
= fd_info
[ p
->outfd
].hnd
;
8930 childp2
= Fcopy_sequence (p
->childp
);
8932 /* Initialize timeouts for blocking read and blocking write. */
8933 if (!GetCommTimeouts (hnd
, &ct
))
8934 error ("GetCommTimeouts() failed");
8935 ct
.ReadIntervalTimeout
= 0;
8936 ct
.ReadTotalTimeoutMultiplier
= 0;
8937 ct
.ReadTotalTimeoutConstant
= 0;
8938 ct
.WriteTotalTimeoutMultiplier
= 0;
8939 ct
.WriteTotalTimeoutConstant
= 0;
8940 if (!SetCommTimeouts (hnd
, &ct
))
8941 error ("SetCommTimeouts() failed");
8942 /* Read port attributes and prepare default configuration. */
8943 memset (&dcb
, 0, sizeof (dcb
));
8944 dcb
.DCBlength
= sizeof (DCB
);
8945 if (!GetCommState (hnd
, &dcb
))
8946 error ("GetCommState() failed");
8949 dcb
.fAbortOnError
= FALSE
;
8950 /* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
8955 /* Configure speed. */
8956 if (!NILP (Fplist_member (contact
, QCspeed
)))
8957 tem
= Fplist_get (contact
, QCspeed
);
8959 tem
= Fplist_get (p
->childp
, QCspeed
);
8961 dcb
.BaudRate
= XINT (tem
);
8962 childp2
= Fplist_put (childp2
, QCspeed
, tem
);
8964 /* Configure bytesize. */
8965 if (!NILP (Fplist_member (contact
, QCbytesize
)))
8966 tem
= Fplist_get (contact
, QCbytesize
);
8968 tem
= Fplist_get (p
->childp
, QCbytesize
);
8970 tem
= make_number (8);
8972 if (XINT (tem
) != 7 && XINT (tem
) != 8)
8973 error (":bytesize must be nil (8), 7, or 8");
8974 dcb
.ByteSize
= XINT (tem
);
8975 summary
[0] = XINT (tem
) + '0';
8976 childp2
= Fplist_put (childp2
, QCbytesize
, tem
);
8978 /* Configure parity. */
8979 if (!NILP (Fplist_member (contact
, QCparity
)))
8980 tem
= Fplist_get (contact
, QCparity
);
8982 tem
= Fplist_get (p
->childp
, QCparity
);
8983 if (!NILP (tem
) && !EQ (tem
, Qeven
) && !EQ (tem
, Qodd
))
8984 error (":parity must be nil (no parity), `even', or `odd'");
8985 dcb
.fParity
= FALSE
;
8986 dcb
.Parity
= NOPARITY
;
8987 dcb
.fErrorChar
= FALSE
;
8992 else if (EQ (tem
, Qeven
))
8996 dcb
.Parity
= EVENPARITY
;
8997 dcb
.fErrorChar
= TRUE
;
8999 else if (EQ (tem
, Qodd
))
9003 dcb
.Parity
= ODDPARITY
;
9004 dcb
.fErrorChar
= TRUE
;
9006 childp2
= Fplist_put (childp2
, QCparity
, tem
);
9008 /* Configure stopbits. */
9009 if (!NILP (Fplist_member (contact
, QCstopbits
)))
9010 tem
= Fplist_get (contact
, QCstopbits
);
9012 tem
= Fplist_get (p
->childp
, QCstopbits
);
9014 tem
= make_number (1);
9016 if (XINT (tem
) != 1 && XINT (tem
) != 2)
9017 error (":stopbits must be nil (1 stopbit), 1, or 2");
9018 summary
[2] = XINT (tem
) + '0';
9019 if (XINT (tem
) == 1)
9020 dcb
.StopBits
= ONESTOPBIT
;
9021 else if (XINT (tem
) == 2)
9022 dcb
.StopBits
= TWOSTOPBITS
;
9023 childp2
= Fplist_put (childp2
, QCstopbits
, tem
);
9025 /* Configure flowcontrol. */
9026 if (!NILP (Fplist_member (contact
, QCflowcontrol
)))
9027 tem
= Fplist_get (contact
, QCflowcontrol
);
9029 tem
= Fplist_get (p
->childp
, QCflowcontrol
);
9030 if (!NILP (tem
) && !EQ (tem
, Qhw
) && !EQ (tem
, Qsw
))
9031 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
9032 dcb
.fOutxCtsFlow
= FALSE
;
9033 dcb
.fOutxDsrFlow
= FALSE
;
9034 dcb
.fDtrControl
= DTR_CONTROL_DISABLE
;
9035 dcb
.fDsrSensitivity
= FALSE
;
9036 dcb
.fTXContinueOnXoff
= FALSE
;
9039 dcb
.fRtsControl
= RTS_CONTROL_DISABLE
;
9040 dcb
.XonChar
= 17; /* Control-Q */
9041 dcb
.XoffChar
= 19; /* Control-S */
9044 /* Already configured. */
9046 else if (EQ (tem
, Qhw
))
9048 dcb
.fRtsControl
= RTS_CONTROL_HANDSHAKE
;
9049 dcb
.fOutxCtsFlow
= TRUE
;
9051 else if (EQ (tem
, Qsw
))
9056 childp2
= Fplist_put (childp2
, QCflowcontrol
, tem
);
9058 /* Activate configuration. */
9059 if (!SetCommState (hnd
, &dcb
))
9060 error ("SetCommState() failed");
9062 childp2
= Fplist_put (childp2
, QCsummary
, build_string (summary
));
9063 pset_childp (p
, childp2
);
9069 emacs_gnutls_pull (gnutls_transport_ptr_t p
, void* buf
, size_t sz
)
9073 struct timespec timeout
;
9074 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9075 int fd
= process
->infd
;
9077 n
= sys_read (fd
, (char*)buf
, sz
);
9084 /* Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9085 if (err
== EWOULDBLOCK
)
9088 emacs_gnutls_transport_set_errno (process
->gnutls_state
, err
);
9094 emacs_gnutls_push (gnutls_transport_ptr_t p
, const void* buf
, size_t sz
)
9096 struct Lisp_Process
*process
= (struct Lisp_Process
*)p
;
9097 int fd
= process
->outfd
;
9098 ssize_t n
= sys_write (fd
, buf
, sz
);
9100 /* 0 or more bytes written means everything went fine. */
9104 /* Negative bytes written means we got an error in errno.
9105 Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
9106 emacs_gnutls_transport_set_errno (process
->gnutls_state
,
9107 errno
== EWOULDBLOCK
? EAGAIN
: errno
);
9111 #endif /* HAVE_GNUTLS */