This source file includes following definitions.
- is_windows_9x
- w32_get_internal_run_time
- open_process_token
- get_token_information
- lookup_account_sid
- get_sid_sub_authority
- get_sid_sub_authority_count
- get_security_info
- get_file_security
- set_file_security
- set_named_security_info
- get_security_descriptor_owner
- get_security_descriptor_group
- get_security_descriptor_dacl
- is_valid_sid
- equal_sid
- get_length_sid
- copy_sid
- get_native_system_info
- get_system_times
- create_symbolic_link
- is_valid_security_descriptor
- convert_sd_to_sddl
- convert_sddl_to_sd
- get_adapters_info
- get_adapters_addresses
- reg_open_key_ex_w
- reg_query_value_ex_w
- expand_environment_strings_w
- get_user_default_ui_language
- w32_valid_pointer_p
- w32_init_file_name_codepage
- codepage_for_filenames
- filename_to_utf16
- filename_from_utf16
- filename_to_ansi
- filename_from_ansi
- w32_get_current_directory
- w32_init_current_directory
- getcwd
- buf_next
- buf_prev
- w32_get_nproc
- num_processors
- sample_system_load
- getavg
- getloadavg
- getuid
- geteuid
- getgid
- getegid
- getpwuid
- getgrgid
- getpwnam
- init_user_info
- w32_init_crypt_random
- w32_init_random
- rand_as183
- random
- srandom
- explicit_bzero
- max_filename_mbslen
- normalize_filename
- dostounix_filename
- unixtodos_filename
- crlf_to_lf
- parse_root
- get_long_basename
- w32_get_long_filename
- w32_get_short_filename
- ansi_encode_filename
- is_unc_volume
- unsetenv
- sys_putenv
- init_environment
- emacs_root_dir
- fdutimens
- sys_ctime
- sys_sleep
- lookup_volume_info
- add_volume_info
- GetCachedVolumeInformation
- get_volume_info
- is_fat_volume
- map_w32_filename
- is_exec
- sys_opendir
- sys_closedir
- sys_readdir
- open_unc_volume
- read_unc_volume
- close_unc_volume
- unc_volume_file_attributes
- logon_network_drive
- faccessat
- w32_accessible_directory_p
- sys_access
- sys_chdir
- chmod_worker
- sys_chmod
- lchmod
- sys_creat
- sys_fopen
- sys_link
- sys_mkdir
- sys_open
- openat
- fchmod
- fchmodat
- sys_rename_replace
- sys_rename
- sys_rmdir
- sys_unlink
- initialize_utc_base
- convert_time
- convert_from_timespec
- get_file_security_desc_by_handle
- get_file_security_desc_by_name
- get_rid
- w32_cached_id
- w32_add_to_cache
- get_name_and_id
- get_file_owner_and_group
- is_slow_fs
- stat_worker
- stat
- lstat
- fstatat
- fstat
- utimensat
- sys_umask
- symlink
- is_symlink
- readlink
- readlinkat
- chase_symlinks
- symlinks_supported
- acl_valid
- acl_to_text
- acl_from_text
- acl_free
- acl_get_file
- acl_set_file
- acl_errno_valid
- careadlinkat
- w32_copy_file
- create_toolhelp32_snapshot
- process32_first
- process32_next
- open_thread_token
- impersonate_self
- revert_to_self
- get_process_memory_info
- get_process_working_set_size
- global_memory_status
- global_memory_status_ex
- list_system_processes
- enable_privilege
- restore_privilege
- ltime
- process_times
- system_process_attributes
- w32_memory_info
- term_winsock
- init_winsock
- set_errno
- check_errno
- sys_strerror
- sys_socket
- socket_to_fd
- sys_bind
- sys_connect
- sys_htons
- sys_ntohs
- sys_htonl
- sys_ntohl
- sys_inet_addr
- sys_gethostname
- sys_gethostbyname
- sys_getservbyname
- sys_getpeername
- sys_getaddrinfo
- sys_freeaddrinfo
- sys_shutdown
- sys_setsockopt
- sys_listen
- sys_getsockname
- sys_accept
- sys_recvfrom
- sys_sendto
- fcntl
- sys_close
- sys_dup
- sys_dup2
- pipe2
- _sys_read_ahead
- _sys_wait_accept
- _sys_wait_connect
- sys_read
- sys_write
- network_interface_get_info
- address_prefix_match
- network_interface_list
- network_interface_info
- w32_read_registry
- sys_localtime
- sys_clock
- w32_delayed_load
- check_windows_init_file
- term_ntproc
- init_ntproc
- shutdown_handler
- maybe_load_unicows_dll
- w32_relocate
- w32_my_exename
- realpath
- get_console_font_size
- w32_reexec_emacs
- globals_of_w32
- serial_open
- serial_configure
- register_aux_fd
- emacs_gnutls_pull
- emacs_gnutls_push
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #define DEFER_MS_W32_H
25 #include <config.h>
26
27 #include <mingw_time.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <float.h>
32 #include <io.h>
33 #include <errno.h>
34 #include <fcntl.h>
35 #include <ctype.h>
36 #include <signal.h>
37 #include <sys/file.h>
38 #include <time.h>
39 #include <sys/time.h>
40 #include <sys/utime.h>
41 #include <math.h>
42 #include <nproc.h>
43
44
45 #include <ms-w32.h>
46
47 #include <string.h>
48 #include <mbstring.h>
49
50 #undef access
51 #undef chdir
52 #undef chmod
53 #undef creat
54 #undef ctime
55 #undef fopen
56 #undef link
57 #undef mkdir
58 #undef open
59 #undef rename
60 #undef rmdir
61 #undef unlink
62
63 #undef close
64 #undef dup
65 #undef dup2
66 #undef pipe
67 #undef read
68 #undef write
69
70 #undef strerror
71
72 #undef localtime
73
74 #undef clock
75
76 char *sys_ctime (const time_t *);
77 int sys_chdir (const char *);
78 int sys_creat (const char *, int);
79 FILE *sys_fopen (const char *, const char *);
80 int sys_open (const char *, int, int);
81 int sys_rename (char const *, char const *);
82 int sys_rmdir (const char *);
83 int sys_close (int);
84 int sys_dup2 (int, int);
85 int sys_read (int, char *, unsigned int);
86 int sys_write (int, const void *, unsigned int);
87 struct tm *sys_localtime (const time_t *);
88
89
90
91 char *sys_strerror (int);
92 clock_t sys_clock (void);
93
94 #ifdef HAVE_MODULES
95 extern void dynlib_reset_last_error (void);
96 #endif
97
98 #include "lisp.h"
99 #include "epaths.h"
100
101 #include <pwd.h>
102 #include <grp.h>
103
104 #include <windows.h>
105
106
107 typedef struct _MEMORY_STATUS_EX {
108 DWORD dwLength;
109 DWORD dwMemoryLoad;
110 DWORDLONG ullTotalPhys;
111 DWORDLONG ullAvailPhys;
112 DWORDLONG ullTotalPageFile;
113 DWORDLONG ullAvailPageFile;
114 DWORDLONG ullTotalVirtual;
115 DWORDLONG ullAvailVirtual;
116 DWORDLONG ullAvailExtendedVirtual;
117 } MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
118
119
120
121
122
123
124
125
126
127
128
129
130 PEXCEPTION_POINTERS excptr;
131 PEXCEPTION_RECORD excprec;
132 PCONTEXT ctxrec;
133
134 #include <lmcons.h>
135 #include <shlobj.h>
136
137 #include <tlhelp32.h>
138 #include <psapi.h>
139 #ifndef _MSC_VER
140 #include <w32api.h>
141 #endif
142 #if _WIN32_WINNT < 0x0500
143 #if !defined (__MINGW32__) || __W32API_MAJOR_VERSION < 3 || (__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 15)
144
145
146
147 typedef struct _PROCESS_MEMORY_COUNTERS_EX {
148 DWORD cb;
149 DWORD PageFaultCount;
150 SIZE_T PeakWorkingSetSize;
151 SIZE_T WorkingSetSize;
152 SIZE_T QuotaPeakPagedPoolUsage;
153 SIZE_T QuotaPagedPoolUsage;
154 SIZE_T QuotaPeakNonPagedPoolUsage;
155 SIZE_T QuotaNonPagedPoolUsage;
156 SIZE_T PagefileUsage;
157 SIZE_T PeakPagefileUsage;
158 SIZE_T PrivateUsage;
159 } PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
160 #endif
161 #endif
162
163 #include <winioctl.h>
164 #include <aclapi.h>
165 #include <sddl.h>
166
167 #include <sys/acl.h>
168 #include <acl.h>
169
170
171
172 #ifndef SDDL_REVISION_1
173 #define SDDL_REVISION_1 1
174 #endif
175
176 #if defined(_MSC_VER) || defined(MINGW_W64)
177
178
179
180
181
182 typedef struct _REPARSE_DATA_BUFFER {
183 ULONG ReparseTag;
184 USHORT ReparseDataLength;
185 USHORT Reserved;
186 union {
187 struct {
188 USHORT SubstituteNameOffset;
189 USHORT SubstituteNameLength;
190 USHORT PrintNameOffset;
191 USHORT PrintNameLength;
192 ULONG Flags;
193 WCHAR PathBuffer[1];
194 } SymbolicLinkReparseBuffer;
195 struct {
196 USHORT SubstituteNameOffset;
197 USHORT SubstituteNameLength;
198 USHORT PrintNameOffset;
199 USHORT PrintNameLength;
200 WCHAR PathBuffer[1];
201 } MountPointReparseBuffer;
202 struct {
203 UCHAR DataBuffer[1];
204 } GenericReparseBuffer;
205 } DUMMYUNIONNAME;
206 } REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
207
208 #ifndef FILE_DEVICE_FILE_SYSTEM
209 #define FILE_DEVICE_FILE_SYSTEM 9
210 #endif
211 #ifndef METHOD_BUFFERED
212 #define METHOD_BUFFERED 0
213 #endif
214 #ifndef FILE_ANY_ACCESS
215 #define FILE_ANY_ACCESS 0x00000000
216 #endif
217 #ifndef CTL_CODE
218 #define CTL_CODE(t,f,m,a) (((t)<<16)|((a)<<14)|((f)<<2)|(m))
219 #endif
220
221 #ifndef FSCTL_GET_REPARSE_POINT
222 #define FSCTL_GET_REPARSE_POINT \
223 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
224 #endif
225 #endif
226
227
228 #include <sys/socket.h>
229 #undef socket
230 #undef bind
231 #undef connect
232 #undef htons
233 #undef ntohs
234 #undef htonl
235 #undef ntohl
236 #undef inet_addr
237 #undef gethostname
238 #undef gethostbyname
239 #undef getservbyname
240 #undef getpeername
241 #undef shutdown
242 #undef setsockopt
243 #undef listen
244 #undef getsockname
245 #undef accept
246 #undef recvfrom
247 #undef sendto
248
249
250 #if _WIN32_WINNT < 0x0501
251 # undef ORIG_WIN32_WINNT
252 # define ORIG_WIN32_WINNT _WIN32_WINNT
253 # undef _WIN32_WINNT
254 # define _WIN32_WINNT 0x0501
255 #endif
256
257 #include <iphlpapi.h>
258
259 #ifdef ORIG_WIN32_WINNT
260 # undef _WIN32_WINNT
261 # define _WIN32_WINNT ORIG_WIN32_WINNT
262 # undef ORIG_WIN32_WINNT
263 #endif
264
265 #include <wincrypt.h>
266
267 #include <c-strcase.h>
268 #include <utimens.h>
269
270 #include "w32.h"
271 #include <dirent.h>
272 #include "w32common.h"
273 #include "w32select.h"
274 #include "systime.h"
275 #include "dispextern.h"
276 #include "coding.h"
277
278 #include "careadlinkat.h"
279 #include "allocator.h"
280
281
282 #include "process.h"
283 #include "systty.h"
284
285 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
286 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
287
288 static DWORD get_rid (PSID);
289 static int is_symlink (const char *);
290 static char * chase_symlinks (const char *);
291 static int enable_privilege (LPCTSTR, BOOL, TOKEN_PRIVILEGES *);
292 static int restore_privilege (TOKEN_PRIVILEGES *);
293 static BOOL WINAPI revert_to_self (void);
294
295 static int sys_access (const char *, int);
296 extern void *e_malloc (size_t);
297 extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
298 const struct timespec *, const sigset_t *);
299 extern int sys_dup (int);
300
301
302
303
304
305
306
307
308
309
310
311 static BOOL g_b_init_is_windows_9x;
312 static BOOL g_b_init_open_process_token;
313 static BOOL g_b_init_get_token_information;
314 static BOOL g_b_init_lookup_account_sid;
315 static BOOL g_b_init_get_sid_sub_authority;
316 static BOOL g_b_init_get_sid_sub_authority_count;
317 static BOOL g_b_init_get_security_info;
318 static BOOL g_b_init_get_file_security_w;
319 static BOOL g_b_init_get_file_security_a;
320 static BOOL g_b_init_get_security_descriptor_owner;
321 static BOOL g_b_init_get_security_descriptor_group;
322 static BOOL g_b_init_is_valid_sid;
323 static BOOL g_b_init_create_toolhelp32_snapshot;
324 static BOOL g_b_init_process32_first;
325 static BOOL g_b_init_process32_next;
326 static BOOL g_b_init_open_thread_token;
327 static BOOL g_b_init_impersonate_self;
328 static BOOL g_b_init_revert_to_self;
329 static BOOL g_b_init_get_process_memory_info;
330 static BOOL g_b_init_get_process_working_set_size;
331 static BOOL g_b_init_global_memory_status;
332 static BOOL g_b_init_global_memory_status_ex;
333 static BOOL g_b_init_get_length_sid;
334 static BOOL g_b_init_equal_sid;
335 static BOOL g_b_init_copy_sid;
336 static BOOL g_b_init_get_native_system_info;
337 static BOOL g_b_init_get_system_times;
338 static BOOL g_b_init_create_symbolic_link_w;
339 static BOOL g_b_init_create_symbolic_link_a;
340 static BOOL g_b_init_get_security_descriptor_dacl;
341 static BOOL g_b_init_convert_sd_to_sddl;
342 static BOOL g_b_init_convert_sddl_to_sd;
343 static BOOL g_b_init_is_valid_security_descriptor;
344 static BOOL g_b_init_set_file_security_w;
345 static BOOL g_b_init_set_file_security_a;
346 static BOOL g_b_init_set_named_security_info_w;
347 static BOOL g_b_init_set_named_security_info_a;
348 static BOOL g_b_init_get_adapters_info;
349 static BOOL g_b_init_get_adapters_addresses;
350 static BOOL g_b_init_reg_open_key_ex_w;
351 static BOOL g_b_init_reg_query_value_ex_w;
352 static BOOL g_b_init_expand_environment_strings_w;
353 static BOOL g_b_init_get_user_default_ui_language;
354 static BOOL g_b_init_get_console_font_size;
355
356 BOOL g_b_init_compare_string_w;
357 BOOL g_b_init_debug_break_process;
358
359
360
361
362
363
364
365 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
366 HANDLE ProcessHandle,
367 DWORD DesiredAccess,
368 PHANDLE TokenHandle);
369 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
370 HANDLE TokenHandle,
371 TOKEN_INFORMATION_CLASS TokenInformationClass,
372 LPVOID TokenInformation,
373 DWORD TokenInformationLength,
374 PDWORD ReturnLength);
375 typedef BOOL (WINAPI * GetProcessTimes_Proc) (
376 HANDLE process_handle,
377 LPFILETIME creation_time,
378 LPFILETIME exit_time,
379 LPFILETIME kernel_time,
380 LPFILETIME user_time);
381
382 GetProcessTimes_Proc get_process_times_fn = NULL;
383
384 #ifdef _UNICODE
385 const char * const LookupAccountSid_Name = "LookupAccountSidW";
386 #else
387 const char * const LookupAccountSid_Name = "LookupAccountSidA";
388 #endif
389 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
390 LPCTSTR lpSystemName,
391 PSID Sid,
392 LPTSTR Name,
393 LPDWORD cbName,
394 LPTSTR DomainName,
395 LPDWORD cbDomainName,
396 PSID_NAME_USE peUse);
397 typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
398 PSID pSid,
399 DWORD n);
400 typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) (
401 PSID pSid);
402 typedef DWORD (WINAPI * GetSecurityInfo_Proc) (
403 HANDLE handle,
404 SE_OBJECT_TYPE ObjectType,
405 SECURITY_INFORMATION SecurityInfo,
406 PSID *ppsidOwner,
407 PSID *ppsidGroup,
408 PACL *ppDacl,
409 PACL *ppSacl,
410 PSECURITY_DESCRIPTOR *ppSecurityDescriptor);
411 typedef BOOL (WINAPI * GetFileSecurityW_Proc) (
412 LPCWSTR lpFileName,
413 SECURITY_INFORMATION RequestedInformation,
414 PSECURITY_DESCRIPTOR pSecurityDescriptor,
415 DWORD nLength,
416 LPDWORD lpnLengthNeeded);
417 typedef BOOL (WINAPI * GetFileSecurityA_Proc) (
418 LPCSTR lpFileName,
419 SECURITY_INFORMATION RequestedInformation,
420 PSECURITY_DESCRIPTOR pSecurityDescriptor,
421 DWORD nLength,
422 LPDWORD lpnLengthNeeded);
423 typedef BOOL (WINAPI *SetFileSecurityW_Proc) (
424 LPCWSTR lpFileName,
425 SECURITY_INFORMATION SecurityInformation,
426 PSECURITY_DESCRIPTOR pSecurityDescriptor);
427 typedef BOOL (WINAPI *SetFileSecurityA_Proc) (
428 LPCSTR lpFileName,
429 SECURITY_INFORMATION SecurityInformation,
430 PSECURITY_DESCRIPTOR pSecurityDescriptor);
431 typedef DWORD (WINAPI *SetNamedSecurityInfoW_Proc) (
432 LPCWSTR lpObjectName,
433 SE_OBJECT_TYPE ObjectType,
434 SECURITY_INFORMATION SecurityInformation,
435 PSID psidOwner,
436 PSID psidGroup,
437 PACL pDacl,
438 PACL pSacl);
439 typedef DWORD (WINAPI *SetNamedSecurityInfoA_Proc) (
440 LPCSTR lpObjectName,
441 SE_OBJECT_TYPE ObjectType,
442 SECURITY_INFORMATION SecurityInformation,
443 PSID psidOwner,
444 PSID psidGroup,
445 PACL pDacl,
446 PACL pSacl);
447 typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
448 PSECURITY_DESCRIPTOR pSecurityDescriptor,
449 PSID *pOwner,
450 LPBOOL lpbOwnerDefaulted);
451 typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
452 PSECURITY_DESCRIPTOR pSecurityDescriptor,
453 PSID *pGroup,
454 LPBOOL lpbGroupDefaulted);
455 typedef BOOL (WINAPI *GetSecurityDescriptorDacl_Proc) (
456 PSECURITY_DESCRIPTOR pSecurityDescriptor,
457 LPBOOL lpbDaclPresent,
458 PACL *pDacl,
459 LPBOOL lpbDaclDefaulted);
460 typedef BOOL (WINAPI * IsValidSid_Proc) (
461 PSID sid);
462 typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
463 DWORD dwFlags,
464 DWORD th32ProcessID);
465 typedef BOOL (WINAPI * Process32First_Proc) (
466 HANDLE hSnapshot,
467 LPPROCESSENTRY32 lppe);
468 typedef BOOL (WINAPI * Process32Next_Proc) (
469 HANDLE hSnapshot,
470 LPPROCESSENTRY32 lppe);
471 typedef BOOL (WINAPI * OpenThreadToken_Proc) (
472 HANDLE ThreadHandle,
473 DWORD DesiredAccess,
474 BOOL OpenAsSelf,
475 PHANDLE TokenHandle);
476 typedef BOOL (WINAPI * ImpersonateSelf_Proc) (
477 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel);
478 typedef BOOL (WINAPI * RevertToSelf_Proc) (void);
479 typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
480 HANDLE Process,
481 PPROCESS_MEMORY_COUNTERS ppsmemCounters,
482 DWORD cb);
483 typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
484 HANDLE hProcess,
485 PSIZE_T lpMinimumWorkingSetSize,
486 PSIZE_T lpMaximumWorkingSetSize);
487 typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
488 LPMEMORYSTATUS lpBuffer);
489 typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
490 LPMEMORY_STATUS_EX lpBuffer);
491 typedef BOOL (WINAPI * CopySid_Proc) (
492 DWORD nDestinationSidLength,
493 PSID pDestinationSid,
494 PSID pSourceSid);
495 typedef BOOL (WINAPI * EqualSid_Proc) (
496 PSID pSid1,
497 PSID pSid2);
498 typedef DWORD (WINAPI * GetLengthSid_Proc) (
499 PSID pSid);
500 typedef void (WINAPI * GetNativeSystemInfo_Proc) (
501 LPSYSTEM_INFO lpSystemInfo);
502 typedef BOOL (WINAPI * GetSystemTimes_Proc) (
503 LPFILETIME lpIdleTime,
504 LPFILETIME lpKernelTime,
505 LPFILETIME lpUserTime);
506 typedef BOOLEAN (WINAPI *CreateSymbolicLinkW_Proc) (
507 LPCWSTR lpSymlinkFileName,
508 LPCWSTR lpTargetFileName,
509 DWORD dwFlags);
510 typedef BOOLEAN (WINAPI *CreateSymbolicLinkA_Proc) (
511 LPCSTR lpSymlinkFileName,
512 LPCSTR lpTargetFileName,
513 DWORD dwFlags);
514 typedef BOOL (WINAPI *ConvertStringSecurityDescriptorToSecurityDescriptor_Proc) (
515 LPCTSTR StringSecurityDescriptor,
516 DWORD StringSDRevision,
517 PSECURITY_DESCRIPTOR *SecurityDescriptor,
518 PULONG SecurityDescriptorSize);
519 typedef BOOL (WINAPI *ConvertSecurityDescriptorToStringSecurityDescriptor_Proc) (
520 PSECURITY_DESCRIPTOR SecurityDescriptor,
521 DWORD RequestedStringSDRevision,
522 SECURITY_INFORMATION SecurityInformation,
523 LPTSTR *StringSecurityDescriptor,
524 PULONG StringSecurityDescriptorLen);
525 typedef BOOL (WINAPI *IsValidSecurityDescriptor_Proc) (PSECURITY_DESCRIPTOR);
526 typedef DWORD (WINAPI *GetAdaptersInfo_Proc) (
527 PIP_ADAPTER_INFO pAdapterInfo,
528 PULONG pOutBufLen);
529 typedef DWORD (WINAPI *GetAdaptersAddresses_Proc) (
530 ULONG,
531 ULONG,
532 PVOID,
533 PIP_ADAPTER_ADDRESSES,
534 PULONG);
535
536 int (WINAPI *pMultiByteToWideChar)(UINT,DWORD,LPCSTR,int,LPWSTR,int);
537 int (WINAPI *pWideCharToMultiByte)(UINT,DWORD,LPCWSTR,int,LPSTR,int,LPCSTR,LPBOOL);
538 DWORD multiByteToWideCharFlags;
539 typedef LONG (WINAPI *RegOpenKeyExW_Proc) (HKEY,LPCWSTR,DWORD,REGSAM,PHKEY);
540 typedef LONG (WINAPI *RegQueryValueExW_Proc) (HKEY,LPCWSTR,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
541 typedef DWORD (WINAPI *ExpandEnvironmentStringsW_Proc) (LPCWSTR,LPWSTR,DWORD);
542 typedef LANGID (WINAPI *GetUserDefaultUILanguage_Proc) (void);
543
544 typedef COORD (WINAPI *GetConsoleFontSize_Proc) (HANDLE, DWORD);
545
546
547
548
549
550
551 #if _WIN32_WINNT < 0x0501 \
552 && (__W32API_MAJOR_VERSION > 5 \
553 || (__W32API_MAJOR_VERSION == 5 && __W32API_MINOR_VERSION >= 2))
554 typedef struct
555 {
556 DWORD nFont;
557 COORD dwFontSize;
558 } CONSOLE_FONT_INFO;
559 #endif
560
561 typedef BOOL (WINAPI *GetCurrentConsoleFont_Proc) (
562 HANDLE,
563 BOOL,
564 CONSOLE_FONT_INFO *);
565
566
567
568 static BOOL
569 is_windows_9x (void)
570 {
571 static BOOL s_b_ret = 0;
572 OSVERSIONINFO os_ver;
573 if (g_b_init_is_windows_9x == 0)
574 {
575 g_b_init_is_windows_9x = 1;
576 ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
577 os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
578 if (GetVersionEx (&os_ver))
579 {
580 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
581 }
582 }
583 return s_b_ret;
584 }
585
586 static Lisp_Object ltime (ULONGLONG);
587
588
589
590
591 Lisp_Object
592 w32_get_internal_run_time (void)
593 {
594 if (get_process_times_fn)
595 {
596 FILETIME create, exit, kernel, user;
597 HANDLE proc = GetCurrentProcess ();
598 if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
599 {
600 LARGE_INTEGER user_int, kernel_int, total;
601 user_int.LowPart = user.dwLowDateTime;
602 user_int.HighPart = user.dwHighDateTime;
603 kernel_int.LowPart = kernel.dwLowDateTime;
604 kernel_int.HighPart = kernel.dwHighDateTime;
605 total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
606 return ltime (total.QuadPart);
607 }
608 }
609
610 return Fcurrent_time ();
611 }
612
613
614
615 static BOOL WINAPI
616 open_process_token (HANDLE ProcessHandle,
617 DWORD DesiredAccess,
618 PHANDLE TokenHandle)
619 {
620 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
621 HMODULE hm_advapi32 = NULL;
622 if (is_windows_9x () == TRUE)
623 {
624 return FALSE;
625 }
626 if (g_b_init_open_process_token == 0)
627 {
628 g_b_init_open_process_token = 1;
629 hm_advapi32 = LoadLibrary ("Advapi32.dll");
630 s_pfn_Open_Process_Token = (OpenProcessToken_Proc)
631 get_proc_addr (hm_advapi32, "OpenProcessToken");
632 }
633 if (s_pfn_Open_Process_Token == NULL)
634 {
635 return FALSE;
636 }
637 return (
638 s_pfn_Open_Process_Token (
639 ProcessHandle,
640 DesiredAccess,
641 TokenHandle)
642 );
643 }
644
645 static BOOL WINAPI
646 get_token_information (HANDLE TokenHandle,
647 TOKEN_INFORMATION_CLASS TokenInformationClass,
648 LPVOID TokenInformation,
649 DWORD TokenInformationLength,
650 PDWORD ReturnLength)
651 {
652 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
653 HMODULE hm_advapi32 = NULL;
654 if (is_windows_9x () == TRUE)
655 {
656 return FALSE;
657 }
658 if (g_b_init_get_token_information == 0)
659 {
660 g_b_init_get_token_information = 1;
661 hm_advapi32 = LoadLibrary ("Advapi32.dll");
662 s_pfn_Get_Token_Information = (GetTokenInformation_Proc)
663 get_proc_addr (hm_advapi32, "GetTokenInformation");
664 }
665 if (s_pfn_Get_Token_Information == NULL)
666 {
667 return FALSE;
668 }
669 return (
670 s_pfn_Get_Token_Information (
671 TokenHandle,
672 TokenInformationClass,
673 TokenInformation,
674 TokenInformationLength,
675 ReturnLength)
676 );
677 }
678
679 static BOOL WINAPI
680 lookup_account_sid (LPCTSTR lpSystemName,
681 PSID Sid,
682 LPTSTR Name,
683 LPDWORD cbName,
684 LPTSTR DomainName,
685 LPDWORD cbDomainName,
686 PSID_NAME_USE peUse)
687 {
688 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
689 HMODULE hm_advapi32 = NULL;
690 if (is_windows_9x () == TRUE)
691 {
692 return FALSE;
693 }
694 if (g_b_init_lookup_account_sid == 0)
695 {
696 g_b_init_lookup_account_sid = 1;
697 hm_advapi32 = LoadLibrary ("Advapi32.dll");
698 s_pfn_Lookup_Account_Sid = (LookupAccountSid_Proc)
699 get_proc_addr (hm_advapi32, LookupAccountSid_Name);
700 }
701 if (s_pfn_Lookup_Account_Sid == NULL)
702 {
703 return FALSE;
704 }
705 return (
706 s_pfn_Lookup_Account_Sid (
707 lpSystemName,
708 Sid,
709 Name,
710 cbName,
711 DomainName,
712 cbDomainName,
713 peUse)
714 );
715 }
716
717 static PDWORD WINAPI
718 get_sid_sub_authority (PSID pSid, DWORD n)
719 {
720 static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
721 static DWORD zero = 0U;
722 HMODULE hm_advapi32 = NULL;
723 if (is_windows_9x () == TRUE)
724 {
725 return &zero;
726 }
727 if (g_b_init_get_sid_sub_authority == 0)
728 {
729 g_b_init_get_sid_sub_authority = 1;
730 hm_advapi32 = LoadLibrary ("Advapi32.dll");
731 s_pfn_Get_Sid_Sub_Authority = (GetSidSubAuthority_Proc)
732 get_proc_addr (hm_advapi32, "GetSidSubAuthority");
733 }
734 if (s_pfn_Get_Sid_Sub_Authority == NULL)
735 {
736 return &zero;
737 }
738 return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
739 }
740
741 static PUCHAR WINAPI
742 get_sid_sub_authority_count (PSID pSid)
743 {
744 static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
745 static UCHAR zero = 0U;
746 HMODULE hm_advapi32 = NULL;
747 if (is_windows_9x () == TRUE)
748 {
749 return &zero;
750 }
751 if (g_b_init_get_sid_sub_authority_count == 0)
752 {
753 g_b_init_get_sid_sub_authority_count = 1;
754 hm_advapi32 = LoadLibrary ("Advapi32.dll");
755 s_pfn_Get_Sid_Sub_Authority_Count = (GetSidSubAuthorityCount_Proc)
756 get_proc_addr (hm_advapi32, "GetSidSubAuthorityCount");
757 }
758 if (s_pfn_Get_Sid_Sub_Authority_Count == NULL)
759 {
760 return &zero;
761 }
762 return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
763 }
764
765 static DWORD WINAPI
766 get_security_info (HANDLE handle,
767 SE_OBJECT_TYPE ObjectType,
768 SECURITY_INFORMATION SecurityInfo,
769 PSID *ppsidOwner,
770 PSID *ppsidGroup,
771 PACL *ppDacl,
772 PACL *ppSacl,
773 PSECURITY_DESCRIPTOR *ppSecurityDescriptor)
774 {
775 static GetSecurityInfo_Proc s_pfn_Get_Security_Info = NULL;
776 HMODULE hm_advapi32 = NULL;
777 if (is_windows_9x () == TRUE)
778 {
779 return FALSE;
780 }
781 if (g_b_init_get_security_info == 0)
782 {
783 g_b_init_get_security_info = 1;
784 hm_advapi32 = LoadLibrary ("Advapi32.dll");
785 s_pfn_Get_Security_Info = (GetSecurityInfo_Proc)
786 get_proc_addr (hm_advapi32, "GetSecurityInfo");
787 }
788 if (s_pfn_Get_Security_Info == NULL)
789 {
790 return FALSE;
791 }
792 return (s_pfn_Get_Security_Info (handle, ObjectType, SecurityInfo,
793 ppsidOwner, ppsidGroup, ppDacl, ppSacl,
794 ppSecurityDescriptor));
795 }
796
797 static BOOL WINAPI
798 get_file_security (const char *lpFileName,
799 SECURITY_INFORMATION RequestedInformation,
800 PSECURITY_DESCRIPTOR pSecurityDescriptor,
801 DWORD nLength,
802 LPDWORD lpnLengthNeeded)
803 {
804 static GetFileSecurityA_Proc s_pfn_Get_File_SecurityA = NULL;
805 static GetFileSecurityW_Proc s_pfn_Get_File_SecurityW = NULL;
806 HMODULE hm_advapi32 = NULL;
807 if (is_windows_9x () == TRUE)
808 {
809 errno = ENOTSUP;
810 return FALSE;
811 }
812 if (w32_unicode_filenames)
813 {
814 wchar_t filename_w[MAX_PATH];
815
816 if (g_b_init_get_file_security_w == 0)
817 {
818 g_b_init_get_file_security_w = 1;
819 hm_advapi32 = LoadLibrary ("Advapi32.dll");
820 s_pfn_Get_File_SecurityW = (GetFileSecurityW_Proc)
821 get_proc_addr (hm_advapi32, "GetFileSecurityW");
822 }
823 if (s_pfn_Get_File_SecurityW == NULL)
824 {
825 errno = ENOTSUP;
826 return FALSE;
827 }
828 filename_to_utf16 (lpFileName, filename_w);
829 return (s_pfn_Get_File_SecurityW (filename_w, RequestedInformation,
830 pSecurityDescriptor, nLength,
831 lpnLengthNeeded));
832 }
833 else
834 {
835 char filename_a[MAX_PATH];
836
837 if (g_b_init_get_file_security_a == 0)
838 {
839 g_b_init_get_file_security_a = 1;
840 hm_advapi32 = LoadLibrary ("Advapi32.dll");
841 s_pfn_Get_File_SecurityA = (GetFileSecurityA_Proc)
842 get_proc_addr (hm_advapi32, "GetFileSecurityA");
843 }
844 if (s_pfn_Get_File_SecurityA == NULL)
845 {
846 errno = ENOTSUP;
847 return FALSE;
848 }
849 filename_to_ansi (lpFileName, filename_a);
850 return (s_pfn_Get_File_SecurityA (filename_a, RequestedInformation,
851 pSecurityDescriptor, nLength,
852 lpnLengthNeeded));
853 }
854 }
855
856 static BOOL WINAPI
857 set_file_security (const char *lpFileName,
858 SECURITY_INFORMATION SecurityInformation,
859 PSECURITY_DESCRIPTOR pSecurityDescriptor)
860 {
861 static SetFileSecurityW_Proc s_pfn_Set_File_SecurityW = NULL;
862 static SetFileSecurityA_Proc s_pfn_Set_File_SecurityA = NULL;
863 HMODULE hm_advapi32 = NULL;
864 if (is_windows_9x () == TRUE)
865 {
866 errno = ENOTSUP;
867 return FALSE;
868 }
869 if (w32_unicode_filenames)
870 {
871 wchar_t filename_w[MAX_PATH];
872
873 if (g_b_init_set_file_security_w == 0)
874 {
875 g_b_init_set_file_security_w = 1;
876 hm_advapi32 = LoadLibrary ("Advapi32.dll");
877 s_pfn_Set_File_SecurityW = (SetFileSecurityW_Proc)
878 get_proc_addr (hm_advapi32, "SetFileSecurityW");
879 }
880 if (s_pfn_Set_File_SecurityW == NULL)
881 {
882 errno = ENOTSUP;
883 return FALSE;
884 }
885 filename_to_utf16 (lpFileName, filename_w);
886 return (s_pfn_Set_File_SecurityW (filename_w, SecurityInformation,
887 pSecurityDescriptor));
888 }
889 else
890 {
891 char filename_a[MAX_PATH];
892
893 if (g_b_init_set_file_security_a == 0)
894 {
895 g_b_init_set_file_security_a = 1;
896 hm_advapi32 = LoadLibrary ("Advapi32.dll");
897 s_pfn_Set_File_SecurityA = (SetFileSecurityA_Proc)
898 get_proc_addr (hm_advapi32, "SetFileSecurityA");
899 }
900 if (s_pfn_Set_File_SecurityA == NULL)
901 {
902 errno = ENOTSUP;
903 return FALSE;
904 }
905 filename_to_ansi (lpFileName, filename_a);
906 return (s_pfn_Set_File_SecurityA (filename_a, SecurityInformation,
907 pSecurityDescriptor));
908 }
909 }
910
911 static DWORD WINAPI
912 set_named_security_info (LPCTSTR lpObjectName,
913 SE_OBJECT_TYPE ObjectType,
914 SECURITY_INFORMATION SecurityInformation,
915 PSID psidOwner,
916 PSID psidGroup,
917 PACL pDacl,
918 PACL pSacl)
919 {
920 static SetNamedSecurityInfoW_Proc s_pfn_Set_Named_Security_InfoW = NULL;
921 static SetNamedSecurityInfoA_Proc s_pfn_Set_Named_Security_InfoA = NULL;
922 HMODULE hm_advapi32 = NULL;
923 if (is_windows_9x () == TRUE)
924 {
925 errno = ENOTSUP;
926 return ENOTSUP;
927 }
928 if (w32_unicode_filenames)
929 {
930 wchar_t filename_w[MAX_PATH];
931
932 if (g_b_init_set_named_security_info_w == 0)
933 {
934 g_b_init_set_named_security_info_w = 1;
935 hm_advapi32 = LoadLibrary ("Advapi32.dll");
936 s_pfn_Set_Named_Security_InfoW = (SetNamedSecurityInfoW_Proc)
937 get_proc_addr (hm_advapi32, "SetNamedSecurityInfoW");
938 }
939 if (s_pfn_Set_Named_Security_InfoW == NULL)
940 {
941 errno = ENOTSUP;
942 return ENOTSUP;
943 }
944 filename_to_utf16 (lpObjectName, filename_w);
945 return (s_pfn_Set_Named_Security_InfoW (filename_w, ObjectType,
946 SecurityInformation, psidOwner,
947 psidGroup, pDacl, pSacl));
948 }
949 else
950 {
951 char filename_a[MAX_PATH];
952
953 if (g_b_init_set_named_security_info_a == 0)
954 {
955 g_b_init_set_named_security_info_a = 1;
956 hm_advapi32 = LoadLibrary ("Advapi32.dll");
957 s_pfn_Set_Named_Security_InfoA = (SetNamedSecurityInfoA_Proc)
958 get_proc_addr (hm_advapi32, "SetNamedSecurityInfoA");
959 }
960 if (s_pfn_Set_Named_Security_InfoA == NULL)
961 {
962 errno = ENOTSUP;
963 return ENOTSUP;
964 }
965 filename_to_ansi (lpObjectName, filename_a);
966 return (s_pfn_Set_Named_Security_InfoA (filename_a, ObjectType,
967 SecurityInformation, psidOwner,
968 psidGroup, pDacl, pSacl));
969 }
970 }
971
972 static BOOL WINAPI
973 get_security_descriptor_owner (PSECURITY_DESCRIPTOR pSecurityDescriptor,
974 PSID *pOwner,
975 LPBOOL lpbOwnerDefaulted)
976 {
977 static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL;
978 HMODULE hm_advapi32 = NULL;
979 if (is_windows_9x () == TRUE)
980 {
981 errno = ENOTSUP;
982 return FALSE;
983 }
984 if (g_b_init_get_security_descriptor_owner == 0)
985 {
986 g_b_init_get_security_descriptor_owner = 1;
987 hm_advapi32 = LoadLibrary ("Advapi32.dll");
988 s_pfn_Get_Security_Descriptor_Owner = (GetSecurityDescriptorOwner_Proc)
989 get_proc_addr (hm_advapi32, "GetSecurityDescriptorOwner");
990 }
991 if (s_pfn_Get_Security_Descriptor_Owner == NULL)
992 {
993 errno = ENOTSUP;
994 return FALSE;
995 }
996 return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
997 lpbOwnerDefaulted));
998 }
999
1000 static BOOL WINAPI
1001 get_security_descriptor_group (PSECURITY_DESCRIPTOR pSecurityDescriptor,
1002 PSID *pGroup,
1003 LPBOOL lpbGroupDefaulted)
1004 {
1005 static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL;
1006 HMODULE hm_advapi32 = NULL;
1007 if (is_windows_9x () == TRUE)
1008 {
1009 errno = ENOTSUP;
1010 return FALSE;
1011 }
1012 if (g_b_init_get_security_descriptor_group == 0)
1013 {
1014 g_b_init_get_security_descriptor_group = 1;
1015 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1016 s_pfn_Get_Security_Descriptor_Group = (GetSecurityDescriptorGroup_Proc)
1017 get_proc_addr (hm_advapi32, "GetSecurityDescriptorGroup");
1018 }
1019 if (s_pfn_Get_Security_Descriptor_Group == NULL)
1020 {
1021 errno = ENOTSUP;
1022 return FALSE;
1023 }
1024 return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
1025 lpbGroupDefaulted));
1026 }
1027
1028 static BOOL WINAPI
1029 get_security_descriptor_dacl (PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030 LPBOOL lpbDaclPresent,
1031 PACL *pDacl,
1032 LPBOOL lpbDaclDefaulted)
1033 {
1034 static GetSecurityDescriptorDacl_Proc s_pfn_Get_Security_Descriptor_Dacl = NULL;
1035 HMODULE hm_advapi32 = NULL;
1036 if (is_windows_9x () == TRUE)
1037 {
1038 errno = ENOTSUP;
1039 return FALSE;
1040 }
1041 if (g_b_init_get_security_descriptor_dacl == 0)
1042 {
1043 g_b_init_get_security_descriptor_dacl = 1;
1044 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1045 s_pfn_Get_Security_Descriptor_Dacl = (GetSecurityDescriptorDacl_Proc)
1046 get_proc_addr (hm_advapi32, "GetSecurityDescriptorDacl");
1047 }
1048 if (s_pfn_Get_Security_Descriptor_Dacl == NULL)
1049 {
1050 errno = ENOTSUP;
1051 return FALSE;
1052 }
1053 return (s_pfn_Get_Security_Descriptor_Dacl (pSecurityDescriptor,
1054 lpbDaclPresent, pDacl,
1055 lpbDaclDefaulted));
1056 }
1057
1058 static BOOL WINAPI
1059 is_valid_sid (PSID sid)
1060 {
1061 static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
1062 HMODULE hm_advapi32 = NULL;
1063 if (is_windows_9x () == TRUE)
1064 {
1065 return FALSE;
1066 }
1067 if (g_b_init_is_valid_sid == 0)
1068 {
1069 g_b_init_is_valid_sid = 1;
1070 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1071 s_pfn_Is_Valid_Sid = (IsValidSid_Proc)
1072 get_proc_addr (hm_advapi32, "IsValidSid");
1073 }
1074 if (s_pfn_Is_Valid_Sid == NULL)
1075 {
1076 return FALSE;
1077 }
1078 return (s_pfn_Is_Valid_Sid (sid));
1079 }
1080
1081 static BOOL WINAPI
1082 equal_sid (PSID sid1, PSID sid2)
1083 {
1084 static EqualSid_Proc s_pfn_Equal_Sid = NULL;
1085 HMODULE hm_advapi32 = NULL;
1086 if (is_windows_9x () == TRUE)
1087 {
1088 return FALSE;
1089 }
1090 if (g_b_init_equal_sid == 0)
1091 {
1092 g_b_init_equal_sid = 1;
1093 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1094 s_pfn_Equal_Sid = (EqualSid_Proc)
1095 get_proc_addr (hm_advapi32, "EqualSid");
1096 }
1097 if (s_pfn_Equal_Sid == NULL)
1098 {
1099 return FALSE;
1100 }
1101 return (s_pfn_Equal_Sid (sid1, sid2));
1102 }
1103
1104 static DWORD WINAPI
1105 get_length_sid (PSID sid)
1106 {
1107 static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL;
1108 HMODULE hm_advapi32 = NULL;
1109 if (is_windows_9x () == TRUE)
1110 {
1111 return 0;
1112 }
1113 if (g_b_init_get_length_sid == 0)
1114 {
1115 g_b_init_get_length_sid = 1;
1116 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1117 s_pfn_Get_Length_Sid = (GetLengthSid_Proc)
1118 get_proc_addr (hm_advapi32, "GetLengthSid");
1119 }
1120 if (s_pfn_Get_Length_Sid == NULL)
1121 {
1122 return 0;
1123 }
1124 return (s_pfn_Get_Length_Sid (sid));
1125 }
1126
1127 static BOOL WINAPI
1128 copy_sid (DWORD destlen, PSID dest, PSID src)
1129 {
1130 static CopySid_Proc s_pfn_Copy_Sid = NULL;
1131 HMODULE hm_advapi32 = NULL;
1132 if (is_windows_9x () == TRUE)
1133 {
1134 return FALSE;
1135 }
1136 if (g_b_init_copy_sid == 0)
1137 {
1138 g_b_init_copy_sid = 1;
1139 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1140 s_pfn_Copy_Sid = (CopySid_Proc)
1141 get_proc_addr (hm_advapi32, "CopySid");
1142 }
1143 if (s_pfn_Copy_Sid == NULL)
1144 {
1145 return FALSE;
1146 }
1147 return (s_pfn_Copy_Sid (destlen, dest, src));
1148 }
1149
1150
1151
1152
1153
1154
1155
1156 static void WINAPI
1157 get_native_system_info (LPSYSTEM_INFO lpSystemInfo)
1158 {
1159 static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
1160 if (is_windows_9x () != TRUE)
1161 {
1162 if (g_b_init_get_native_system_info == 0)
1163 {
1164 g_b_init_get_native_system_info = 1;
1165 s_pfn_Get_Native_System_Info = (GetNativeSystemInfo_Proc)
1166 get_proc_addr (GetModuleHandle ("kernel32.dll"),
1167 "GetNativeSystemInfo");
1168 }
1169 if (s_pfn_Get_Native_System_Info != NULL)
1170 s_pfn_Get_Native_System_Info (lpSystemInfo);
1171 }
1172 else
1173 lpSystemInfo->dwNumberOfProcessors = -1;
1174 }
1175
1176 static BOOL WINAPI
1177 get_system_times (LPFILETIME lpIdleTime,
1178 LPFILETIME lpKernelTime,
1179 LPFILETIME lpUserTime)
1180 {
1181 static GetSystemTimes_Proc s_pfn_Get_System_times = NULL;
1182 if (is_windows_9x () == TRUE)
1183 {
1184 return FALSE;
1185 }
1186 if (g_b_init_get_system_times == 0)
1187 {
1188 g_b_init_get_system_times = 1;
1189 s_pfn_Get_System_times = (GetSystemTimes_Proc)
1190 get_proc_addr (GetModuleHandle ("kernel32.dll"),
1191 "GetSystemTimes");
1192 }
1193 if (s_pfn_Get_System_times == NULL)
1194 return FALSE;
1195 return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime));
1196 }
1197
1198 static BOOLEAN WINAPI
1199 create_symbolic_link (LPCSTR lpSymlinkFilename,
1200 LPCSTR lpTargetFileName,
1201 DWORD dwFlags)
1202 {
1203 static CreateSymbolicLinkW_Proc s_pfn_Create_Symbolic_LinkW = NULL;
1204 static CreateSymbolicLinkA_Proc s_pfn_Create_Symbolic_LinkA = NULL;
1205 BOOLEAN retval;
1206
1207 if (is_windows_9x () == TRUE)
1208 {
1209 errno = ENOSYS;
1210 return 0;
1211 }
1212 if (w32_unicode_filenames)
1213 {
1214 wchar_t symfn_w[MAX_PATH], tgtfn_w[MAX_PATH];
1215
1216 if (g_b_init_create_symbolic_link_w == 0)
1217 {
1218 g_b_init_create_symbolic_link_w = 1;
1219 s_pfn_Create_Symbolic_LinkW = (CreateSymbolicLinkW_Proc)
1220 get_proc_addr (GetModuleHandle ("kernel32.dll"),
1221 "CreateSymbolicLinkW");
1222 }
1223 if (s_pfn_Create_Symbolic_LinkW == NULL)
1224 {
1225 errno = ENOSYS;
1226 return 0;
1227 }
1228
1229 filename_to_utf16 (lpSymlinkFilename, symfn_w);
1230 filename_to_utf16 (lpTargetFileName, tgtfn_w);
1231 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1232
1233
1234 if (!retval)
1235 {
1236 TOKEN_PRIVILEGES priv_current;
1237
1238 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1239 &priv_current))
1240 {
1241 retval = s_pfn_Create_Symbolic_LinkW (symfn_w, tgtfn_w, dwFlags);
1242 restore_privilege (&priv_current);
1243 revert_to_self ();
1244 }
1245 }
1246 }
1247 else
1248 {
1249 char symfn_a[MAX_PATH], tgtfn_a[MAX_PATH];
1250
1251 if (g_b_init_create_symbolic_link_a == 0)
1252 {
1253 g_b_init_create_symbolic_link_a = 1;
1254 s_pfn_Create_Symbolic_LinkA = (CreateSymbolicLinkA_Proc)
1255 get_proc_addr (GetModuleHandle ("kernel32.dll"),
1256 "CreateSymbolicLinkA");
1257 }
1258 if (s_pfn_Create_Symbolic_LinkA == NULL)
1259 {
1260 errno = ENOSYS;
1261 return 0;
1262 }
1263
1264 filename_to_ansi (lpSymlinkFilename, symfn_a);
1265 filename_to_ansi (lpTargetFileName, tgtfn_a);
1266 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1267
1268
1269 if (!retval)
1270 {
1271 TOKEN_PRIVILEGES priv_current;
1272
1273 if (enable_privilege (SE_CREATE_SYMBOLIC_LINK_NAME, TRUE,
1274 &priv_current))
1275 {
1276 retval = s_pfn_Create_Symbolic_LinkA (symfn_a, tgtfn_a, dwFlags);
1277 restore_privilege (&priv_current);
1278 revert_to_self ();
1279 }
1280 }
1281 }
1282 return retval;
1283 }
1284
1285 static BOOL WINAPI
1286 is_valid_security_descriptor (PSECURITY_DESCRIPTOR pSecurityDescriptor)
1287 {
1288 static IsValidSecurityDescriptor_Proc s_pfn_Is_Valid_Security_Descriptor_Proc = NULL;
1289
1290 if (is_windows_9x () == TRUE)
1291 {
1292 errno = ENOTSUP;
1293 return FALSE;
1294 }
1295
1296 if (g_b_init_is_valid_security_descriptor == 0)
1297 {
1298 g_b_init_is_valid_security_descriptor = 1;
1299 s_pfn_Is_Valid_Security_Descriptor_Proc = (IsValidSecurityDescriptor_Proc)
1300 get_proc_addr (GetModuleHandle ("Advapi32.dll"),
1301 "IsValidSecurityDescriptor");
1302 }
1303 if (s_pfn_Is_Valid_Security_Descriptor_Proc == NULL)
1304 {
1305 errno = ENOTSUP;
1306 return FALSE;
1307 }
1308
1309 return s_pfn_Is_Valid_Security_Descriptor_Proc (pSecurityDescriptor);
1310 }
1311
1312 static BOOL WINAPI
1313 convert_sd_to_sddl (PSECURITY_DESCRIPTOR SecurityDescriptor,
1314 DWORD RequestedStringSDRevision,
1315 SECURITY_INFORMATION SecurityInformation,
1316 LPTSTR *StringSecurityDescriptor,
1317 PULONG StringSecurityDescriptorLen)
1318 {
1319 static ConvertSecurityDescriptorToStringSecurityDescriptor_Proc s_pfn_Convert_SD_To_SDDL = NULL;
1320 BOOL retval;
1321
1322 if (is_windows_9x () == TRUE)
1323 {
1324 errno = ENOTSUP;
1325 return FALSE;
1326 }
1327
1328 if (g_b_init_convert_sd_to_sddl == 0)
1329 {
1330 g_b_init_convert_sd_to_sddl = 1;
1331 #ifdef _UNICODE
1332 s_pfn_Convert_SD_To_SDDL =
1333 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
1334 get_proc_addr (GetModuleHandle ("Advapi32.dll"),
1335 "ConvertSecurityDescriptorToStringSecurityDescriptorW");
1336 #else
1337 s_pfn_Convert_SD_To_SDDL =
1338 (ConvertSecurityDescriptorToStringSecurityDescriptor_Proc)
1339 get_proc_addr (GetModuleHandle ("Advapi32.dll"),
1340 "ConvertSecurityDescriptorToStringSecurityDescriptorA");
1341 #endif
1342 }
1343 if (s_pfn_Convert_SD_To_SDDL == NULL)
1344 {
1345 errno = ENOTSUP;
1346 return FALSE;
1347 }
1348
1349 retval = s_pfn_Convert_SD_To_SDDL (SecurityDescriptor,
1350 RequestedStringSDRevision,
1351 SecurityInformation,
1352 StringSecurityDescriptor,
1353 StringSecurityDescriptorLen);
1354
1355 return retval;
1356 }
1357
1358 static BOOL WINAPI
1359 convert_sddl_to_sd (LPCTSTR StringSecurityDescriptor,
1360 DWORD StringSDRevision,
1361 PSECURITY_DESCRIPTOR *SecurityDescriptor,
1362 PULONG SecurityDescriptorSize)
1363 {
1364 static ConvertStringSecurityDescriptorToSecurityDescriptor_Proc s_pfn_Convert_SDDL_To_SD = NULL;
1365 BOOL retval;
1366
1367 if (is_windows_9x () == TRUE)
1368 {
1369 errno = ENOTSUP;
1370 return FALSE;
1371 }
1372
1373 if (g_b_init_convert_sddl_to_sd == 0)
1374 {
1375 g_b_init_convert_sddl_to_sd = 1;
1376 #ifdef _UNICODE
1377 s_pfn_Convert_SDDL_To_SD =
1378 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)
1379 get_proc_addr (GetModuleHandle ("Advapi32.dll"),
1380 "ConvertStringSecurityDescriptorToSecurityDescriptorW");
1381 #else
1382 s_pfn_Convert_SDDL_To_SD =
1383 (ConvertStringSecurityDescriptorToSecurityDescriptor_Proc)
1384 get_proc_addr (GetModuleHandle ("Advapi32.dll"),
1385 "ConvertStringSecurityDescriptorToSecurityDescriptorA");
1386 #endif
1387 }
1388 if (s_pfn_Convert_SDDL_To_SD == NULL)
1389 {
1390 errno = ENOTSUP;
1391 return FALSE;
1392 }
1393
1394 retval = s_pfn_Convert_SDDL_To_SD (StringSecurityDescriptor,
1395 StringSDRevision,
1396 SecurityDescriptor,
1397 SecurityDescriptorSize);
1398
1399 return retval;
1400 }
1401
1402 static DWORD WINAPI
1403 get_adapters_info (PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
1404 {
1405 static GetAdaptersInfo_Proc s_pfn_Get_Adapters_Info = NULL;
1406 HMODULE hm_iphlpapi = NULL;
1407
1408 if (is_windows_9x () == TRUE)
1409 return ERROR_NOT_SUPPORTED;
1410
1411 if (g_b_init_get_adapters_info == 0)
1412 {
1413 g_b_init_get_adapters_info = 1;
1414 hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
1415 if (hm_iphlpapi)
1416 s_pfn_Get_Adapters_Info = (GetAdaptersInfo_Proc)
1417 get_proc_addr (hm_iphlpapi, "GetAdaptersInfo");
1418 }
1419 if (s_pfn_Get_Adapters_Info == NULL)
1420 return ERROR_NOT_SUPPORTED;
1421 return s_pfn_Get_Adapters_Info (pAdapterInfo, pOutBufLen);
1422 }
1423
1424 static DWORD WINAPI
1425 get_adapters_addresses (ULONG family, PIP_ADAPTER_ADDRESSES pAdapterAddresses, PULONG pOutBufLen)
1426 {
1427 static GetAdaptersAddresses_Proc s_pfn_Get_Adapters_Addresses = NULL;
1428 HMODULE hm_iphlpapi = NULL;
1429
1430 if (is_windows_9x () == TRUE)
1431 return ERROR_NOT_SUPPORTED;
1432
1433 if (g_b_init_get_adapters_addresses == 0)
1434 {
1435 g_b_init_get_adapters_addresses = 1;
1436 hm_iphlpapi = LoadLibrary ("Iphlpapi.dll");
1437 if (hm_iphlpapi)
1438 s_pfn_Get_Adapters_Addresses = (GetAdaptersAddresses_Proc)
1439 get_proc_addr (hm_iphlpapi, "GetAdaptersAddresses");
1440 }
1441 if (s_pfn_Get_Adapters_Addresses == NULL)
1442 return ERROR_NOT_SUPPORTED;
1443 ULONG flags = GAA_FLAG_SKIP_ANYCAST
1444 | GAA_FLAG_SKIP_MULTICAST
1445 | GAA_FLAG_SKIP_DNS_SERVER;
1446 return s_pfn_Get_Adapters_Addresses (family, flags, NULL, pAdapterAddresses, pOutBufLen);
1447 }
1448
1449 static LONG WINAPI
1450 reg_open_key_ex_w (HKEY hkey, LPCWSTR lpSubKey, DWORD ulOptions,
1451 REGSAM samDesired, PHKEY phkResult)
1452 {
1453 static RegOpenKeyExW_Proc s_pfn_Reg_Open_Key_Ex_w = NULL;
1454 HMODULE hm_advapi32 = NULL;
1455
1456 if (is_windows_9x () == TRUE)
1457 return ERROR_NOT_SUPPORTED;
1458
1459 if (g_b_init_reg_open_key_ex_w == 0)
1460 {
1461 g_b_init_reg_open_key_ex_w = 1;
1462 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1463 if (hm_advapi32)
1464 s_pfn_Reg_Open_Key_Ex_w = (RegOpenKeyExW_Proc)
1465 get_proc_addr (hm_advapi32, "RegOpenKeyExW");
1466 }
1467 if (s_pfn_Reg_Open_Key_Ex_w == NULL)
1468 return ERROR_NOT_SUPPORTED;
1469 return s_pfn_Reg_Open_Key_Ex_w (hkey, lpSubKey, ulOptions,
1470 samDesired, phkResult);
1471 }
1472
1473 static LONG WINAPI
1474 reg_query_value_ex_w (HKEY hkey, LPCWSTR lpValueName, LPDWORD lpReserved,
1475 LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
1476 {
1477 static RegQueryValueExW_Proc s_pfn_Reg_Query_Value_Ex_w = NULL;
1478 HMODULE hm_advapi32 = NULL;
1479
1480 if (is_windows_9x () == TRUE)
1481 return ERROR_NOT_SUPPORTED;
1482
1483 if (g_b_init_reg_query_value_ex_w == 0)
1484 {
1485 g_b_init_reg_query_value_ex_w = 1;
1486 hm_advapi32 = LoadLibrary ("Advapi32.dll");
1487 if (hm_advapi32)
1488 s_pfn_Reg_Query_Value_Ex_w = (RegQueryValueExW_Proc)
1489 get_proc_addr (hm_advapi32, "RegQueryValueExW");
1490 }
1491 if (s_pfn_Reg_Query_Value_Ex_w == NULL)
1492 return ERROR_NOT_SUPPORTED;
1493 return s_pfn_Reg_Query_Value_Ex_w (hkey, lpValueName, lpReserved,
1494 lpType, lpData, lpcbData);
1495 }
1496
1497 static DWORD WINAPI
1498 expand_environment_strings_w (LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize)
1499 {
1500 static ExpandEnvironmentStringsW_Proc s_pfn_Expand_Environment_Strings_w = NULL;
1501 HMODULE hm_kernel32 = NULL;
1502
1503 if (is_windows_9x () == TRUE)
1504 return ERROR_NOT_SUPPORTED;
1505
1506 if (g_b_init_expand_environment_strings_w == 0)
1507 {
1508 g_b_init_expand_environment_strings_w = 1;
1509 hm_kernel32 = LoadLibrary ("Kernel32.dll");
1510 if (hm_kernel32)
1511 s_pfn_Expand_Environment_Strings_w = (ExpandEnvironmentStringsW_Proc)
1512 get_proc_addr (hm_kernel32, "ExpandEnvironmentStringsW");
1513 }
1514 if (s_pfn_Expand_Environment_Strings_w == NULL)
1515 {
1516 errno = ENOSYS;
1517 return FALSE;
1518 }
1519 return s_pfn_Expand_Environment_Strings_w (lpSrc, lpDst, nSize);
1520 }
1521
1522 static LANGID WINAPI
1523 get_user_default_ui_language (void)
1524 {
1525 static GetUserDefaultUILanguage_Proc s_pfn_GetUserDefaultUILanguage = NULL;
1526 HMODULE hm_kernel32 = NULL;
1527
1528 if (is_windows_9x () == TRUE)
1529 return 0;
1530
1531 if (g_b_init_get_user_default_ui_language == 0)
1532 {
1533 g_b_init_get_user_default_ui_language = 1;
1534 hm_kernel32 = LoadLibrary ("Kernel32.dll");
1535 if (hm_kernel32)
1536 s_pfn_GetUserDefaultUILanguage = (GetUserDefaultUILanguage_Proc)
1537 get_proc_addr (hm_kernel32, "GetUserDefaultUILanguage");
1538 }
1539 if (s_pfn_GetUserDefaultUILanguage == NULL)
1540 return 0;
1541 return s_pfn_GetUserDefaultUILanguage ();
1542 }
1543
1544
1545
1546
1547
1548
1549
1550 int
1551 w32_valid_pointer_p (void *p, int size)
1552 {
1553 SIZE_T done;
1554 HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
1555
1556 if (h)
1557 {
1558 unsigned char *buf = alloca (size);
1559 int retval = ReadProcessMemory (h, p, buf, size, &done);
1560
1561 CloseHandle (h);
1562 return retval;
1563 }
1564 else
1565 return -1;
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678 static int file_name_codepage;
1679
1680
1681
1682
1683 void
1684 w32_init_file_name_codepage (void)
1685 {
1686 file_name_codepage = CP_ACP;
1687 w32_ansi_code_page = CP_ACP;
1688 }
1689
1690
1691
1692 int
1693 codepage_for_filenames (CPINFO *cp_info)
1694 {
1695
1696
1697
1698 static Lisp_Object last_file_name_encoding;
1699 static CPINFO cp;
1700 Lisp_Object current_encoding;
1701
1702 current_encoding = Vfile_name_coding_system;
1703 if (NILP (current_encoding))
1704 current_encoding = Vdefault_file_name_coding_system;
1705
1706 if (!EQ (last_file_name_encoding, current_encoding)
1707 || NILP (last_file_name_encoding))
1708 {
1709
1710 file_name_codepage = w32_ansi_code_page;
1711
1712 if (!NILP (current_encoding))
1713 {
1714 char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
1715 char *cp = NULL, *end;
1716 int cpnum;
1717
1718 if (strncmp (cpname, "cp", 2) == 0)
1719 cp = cpname + 2;
1720 else if (strncmp (cpname, "windows-", 8) == 0)
1721 cp = cpname + 8;
1722
1723 if (cp)
1724 {
1725 end = cp;
1726 cpnum = strtol (cp, &end, 10);
1727 if (cpnum && *end == '\0' && end - cp >= 2)
1728 file_name_codepage = cpnum;
1729 }
1730 }
1731
1732 if (!file_name_codepage)
1733 file_name_codepage = CP_ACP;
1734
1735 if (!GetCPInfo (file_name_codepage, &cp))
1736 {
1737 file_name_codepage = CP_ACP;
1738 if (!GetCPInfo (file_name_codepage, &cp))
1739 emacs_abort ();
1740 }
1741
1742
1743 last_file_name_encoding = current_encoding;
1744 }
1745 if (cp_info)
1746 *cp_info = cp;
1747
1748 return file_name_codepage;
1749 }
1750
1751 int
1752 filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
1753 {
1754 int result = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, fn_in,
1755 -1, fn_out, MAX_PATH);
1756
1757 if (!result)
1758 {
1759 DWORD err = GetLastError ();
1760
1761 switch (err)
1762 {
1763 case ERROR_INVALID_FLAGS:
1764 case ERROR_INVALID_PARAMETER:
1765 errno = EINVAL;
1766 break;
1767 case ERROR_INSUFFICIENT_BUFFER:
1768 case ERROR_NO_UNICODE_TRANSLATION:
1769 default:
1770 errno = ENOENT;
1771 break;
1772 }
1773 return -1;
1774 }
1775 return 0;
1776 }
1777
1778 int
1779 filename_from_utf16 (const wchar_t *fn_in, char *fn_out)
1780 {
1781 int result = pWideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
1782 fn_out, MAX_UTF8_PATH, NULL, NULL);
1783
1784 if (!result)
1785 {
1786 DWORD err = GetLastError ();
1787
1788 switch (err)
1789 {
1790 case ERROR_INVALID_FLAGS:
1791 case ERROR_INVALID_PARAMETER:
1792 errno = EINVAL;
1793 break;
1794 case ERROR_INSUFFICIENT_BUFFER:
1795 case ERROR_NO_UNICODE_TRANSLATION:
1796 default:
1797 errno = ENOENT;
1798 break;
1799 }
1800 return -1;
1801 }
1802 return 0;
1803 }
1804
1805 int
1806 filename_to_ansi (const char *fn_in, char *fn_out)
1807 {
1808 wchar_t fn_utf16[MAX_PATH];
1809
1810 if (filename_to_utf16 (fn_in, fn_utf16) == 0)
1811 {
1812 int result;
1813 int codepage = codepage_for_filenames (NULL);
1814
1815 result = pWideCharToMultiByte (codepage, 0, fn_utf16, -1,
1816 fn_out, MAX_PATH, NULL, NULL);
1817 if (!result)
1818 {
1819 DWORD err = GetLastError ();
1820
1821 switch (err)
1822 {
1823 case ERROR_INVALID_FLAGS:
1824 case ERROR_INVALID_PARAMETER:
1825 errno = EINVAL;
1826 break;
1827 case ERROR_INSUFFICIENT_BUFFER:
1828 case ERROR_NO_UNICODE_TRANSLATION:
1829 default:
1830 errno = ENOENT;
1831 break;
1832 }
1833 return -1;
1834 }
1835 return 0;
1836 }
1837 return -1;
1838 }
1839
1840 int
1841 filename_from_ansi (const char *fn_in, char *fn_out)
1842 {
1843 wchar_t fn_utf16[MAX_PATH];
1844 int codepage = codepage_for_filenames (NULL);
1845 int result = pMultiByteToWideChar (codepage, multiByteToWideCharFlags, fn_in,
1846 -1, fn_utf16, MAX_PATH);
1847
1848 if (!result)
1849 {
1850 DWORD err = GetLastError ();
1851
1852 switch (err)
1853 {
1854 case ERROR_INVALID_FLAGS:
1855 case ERROR_INVALID_PARAMETER:
1856 errno = EINVAL;
1857 break;
1858 case ERROR_INSUFFICIENT_BUFFER:
1859 case ERROR_NO_UNICODE_TRANSLATION:
1860 default:
1861 errno = ENOENT;
1862 break;
1863 }
1864 return -1;
1865 }
1866 return filename_from_utf16 (fn_utf16, fn_out);
1867 }
1868
1869
1870
1871
1872 static char startup_dir[MAX_UTF8_PATH];
1873
1874
1875
1876
1877 static void
1878 w32_get_current_directory (char *cwd)
1879 {
1880
1881
1882 if (w32_unicode_filenames)
1883 {
1884 wchar_t wstartup_dir[MAX_PATH];
1885
1886 if (!GetCurrentDirectoryW (MAX_PATH, wstartup_dir))
1887 emacs_abort ();
1888 filename_from_utf16 (wstartup_dir, cwd);
1889 }
1890 else
1891 {
1892 char astartup_dir[MAX_PATH];
1893
1894 if (!GetCurrentDirectoryA (MAX_PATH, astartup_dir))
1895 emacs_abort ();
1896 filename_from_ansi (astartup_dir, cwd);
1897 }
1898 }
1899
1900
1901 void
1902 w32_init_current_directory (void)
1903 {
1904 w32_get_current_directory (startup_dir);
1905 }
1906
1907
1908 char *
1909 getcwd (char *dir, int dirsize)
1910 {
1911 if (!dirsize)
1912 {
1913 errno = EINVAL;
1914 return NULL;
1915 }
1916 if (dirsize <= strlen (startup_dir))
1917 {
1918 errno = ERANGE;
1919 return NULL;
1920 }
1921 #if 0
1922 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
1923 return dir;
1924 return NULL;
1925 #else
1926
1927
1928 strcpy (dir, startup_dir);
1929 return dir;
1930 #endif
1931 }
1932
1933
1934
1935 struct load_sample {
1936 time_t sample_time;
1937 ULONGLONG idle;
1938 ULONGLONG kernel;
1939 ULONGLONG user;
1940 };
1941
1942
1943 static unsigned num_of_processors;
1944
1945
1946 static struct load_sample samples[16*60];
1947 static int first_idx = -1, last_idx = -1;
1948 static int max_idx = ARRAYELTS (samples);
1949
1950 static int
1951 buf_next (int from)
1952 {
1953 int next_idx = from + 1;
1954
1955 if (next_idx >= max_idx)
1956 next_idx = 0;
1957
1958 return next_idx;
1959 }
1960
1961 static int
1962 buf_prev (int from)
1963 {
1964 int prev_idx = from - 1;
1965
1966 if (prev_idx < 0)
1967 prev_idx = max_idx - 1;
1968
1969 return prev_idx;
1970 }
1971
1972 unsigned
1973 w32_get_nproc (void)
1974 {
1975 SYSTEM_INFO sysinfo;
1976
1977
1978 if (num_of_processors <= 0)
1979 {
1980 get_native_system_info (&sysinfo);
1981 num_of_processors = sysinfo.dwNumberOfProcessors;
1982 if (num_of_processors <= 0)
1983 {
1984 GetSystemInfo (&sysinfo);
1985 num_of_processors = sysinfo.dwNumberOfProcessors;
1986 }
1987 if (num_of_processors <= 0)
1988 num_of_processors = 1;
1989 }
1990 return num_of_processors;
1991 }
1992
1993
1994
1995
1996 unsigned long
1997 num_processors (enum nproc_query query)
1998 {
1999
2000 return w32_get_nproc ();
2001 }
2002
2003 static void
2004 sample_system_load (ULONGLONG *idle, ULONGLONG *kernel, ULONGLONG *user)
2005 {
2006 FILETIME ft_idle, ft_user, ft_kernel;
2007
2008 (void) w32_get_nproc ();
2009
2010
2011
2012
2013
2014
2015 if (get_system_times (&ft_idle, &ft_kernel, &ft_user))
2016 {
2017 ULARGE_INTEGER uidle, ukernel, uuser;
2018
2019 memcpy (&uidle, &ft_idle, sizeof (ft_idle));
2020 memcpy (&ukernel, &ft_kernel, sizeof (ft_kernel));
2021 memcpy (&uuser, &ft_user, sizeof (ft_user));
2022 *idle = uidle.QuadPart;
2023 *kernel = ukernel.QuadPart;
2024 *user = uuser.QuadPart;
2025 }
2026 else
2027 {
2028 *idle = 0;
2029 *kernel = 0;
2030 *user = 0;
2031 }
2032 }
2033
2034
2035
2036
2037 static double
2038 getavg (int which)
2039 {
2040 double retval = -1.0;
2041 double tdiff;
2042 int idx;
2043 double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
2044 time_t now = samples[last_idx].sample_time;
2045
2046 if (first_idx != last_idx)
2047 {
2048 for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
2049 {
2050 tdiff = difftime (now, samples[idx].sample_time);
2051 if (tdiff >= span - 2*DBL_EPSILON*now)
2052 {
2053 long double sys =
2054 samples[last_idx].kernel + samples[last_idx].user
2055 - (samples[idx].kernel + samples[idx].user);
2056 long double idl = samples[last_idx].idle - samples[idx].idle;
2057
2058 retval = (1.0 - idl / sys) * num_of_processors;
2059 break;
2060 }
2061 if (idx == first_idx)
2062 break;
2063 }
2064 }
2065
2066 return retval;
2067 }
2068
2069 int
2070 getloadavg (double loadavg[], int nelem)
2071 {
2072 int elem;
2073 ULONGLONG idle, kernel, user;
2074 time_t now = time (NULL);
2075
2076
2077
2078
2079
2080 if (last_idx >= 0)
2081 {
2082 while (difftime (now, samples[last_idx].sample_time) < -1.0)
2083 {
2084 if (last_idx == first_idx)
2085 {
2086 first_idx = last_idx = -1;
2087 break;
2088 }
2089 last_idx = buf_prev (last_idx);
2090 }
2091 }
2092
2093
2094
2095 if (last_idx < 0
2096 || (difftime (now, samples[last_idx].sample_time)
2097 >= 1.0 - 2*DBL_EPSILON*now))
2098 {
2099 sample_system_load (&idle, &kernel, &user);
2100 last_idx = buf_next (last_idx);
2101 samples[last_idx].sample_time = now;
2102 samples[last_idx].idle = idle;
2103 samples[last_idx].kernel = kernel;
2104 samples[last_idx].user = user;
2105
2106
2107 if (first_idx == -1)
2108 first_idx = last_idx;
2109 while (first_idx != last_idx
2110 && (difftime (now, samples[first_idx].sample_time)
2111 >= 15.0*60 + 2*DBL_EPSILON*now))
2112 first_idx = buf_next (first_idx);
2113 }
2114
2115 for (elem = 0; elem < nelem; elem++)
2116 {
2117 double avg = getavg (elem);
2118
2119 if (avg < 0)
2120 break;
2121 loadavg[elem] = avg;
2122 }
2123
2124
2125
2126
2127
2128 if (elem == 0)
2129 loadavg[elem++] = 0.09;
2130
2131 return elem;
2132 }
2133
2134
2135
2136 #define PASSWD_FIELD_SIZE 256
2137
2138 static char dflt_passwd_name[PASSWD_FIELD_SIZE];
2139 static char dflt_passwd_passwd[PASSWD_FIELD_SIZE];
2140 static char dflt_passwd_gecos[PASSWD_FIELD_SIZE];
2141 static char dflt_passwd_dir[MAX_UTF8_PATH];
2142 static char dflt_passwd_shell[MAX_UTF8_PATH];
2143
2144 static struct passwd dflt_passwd =
2145 {
2146 dflt_passwd_name,
2147 dflt_passwd_passwd,
2148 0,
2149 0,
2150 0,
2151 dflt_passwd_gecos,
2152 dflt_passwd_dir,
2153 dflt_passwd_shell,
2154 };
2155
2156 static char dflt_group_name[GNLEN+1];
2157
2158 static struct group dflt_group =
2159 {
2160
2161
2162 dflt_group_name,
2163 0,
2164 };
2165
2166 unsigned
2167 getuid (void)
2168 {
2169 return dflt_passwd.pw_uid;
2170 }
2171
2172 unsigned
2173 geteuid (void)
2174 {
2175
2176
2177
2178 return getuid ();
2179 }
2180
2181 unsigned
2182 getgid (void)
2183 {
2184 return dflt_passwd.pw_gid;
2185 }
2186
2187 unsigned
2188 getegid (void)
2189 {
2190 return getgid ();
2191 }
2192
2193 struct passwd *
2194 getpwuid (unsigned uid)
2195 {
2196 if (uid == dflt_passwd.pw_uid)
2197 return &dflt_passwd;
2198 return NULL;
2199 }
2200
2201 struct group *
2202 getgrgid (gid_t gid)
2203 {
2204 if (gid == dflt_passwd.pw_gid)
2205 return &dflt_group;
2206 return NULL;
2207 }
2208
2209 struct passwd *
2210 getpwnam (char *name)
2211 {
2212 struct passwd *pw;
2213
2214 pw = getpwuid (getuid ());
2215 if (!pw)
2216 return pw;
2217
2218 if (xstrcasecmp (name, pw->pw_name))
2219 {
2220
2221
2222
2223
2224 char *logname = getenv ("LOGNAME");
2225 char *username = getenv ("USERNAME");
2226 if ((logname || username)
2227 && xstrcasecmp (name, logname ? logname : username) == 0)
2228 {
2229 static struct passwd alias_user;
2230 static char alias_name[PASSWD_FIELD_SIZE];
2231
2232 memcpy (&alias_user, &dflt_passwd, sizeof dflt_passwd);
2233 alias_name[0] = '\0';
2234 strncat (alias_name, logname ? logname : username,
2235 PASSWD_FIELD_SIZE - 1);
2236 alias_user.pw_name = alias_name;
2237 pw = &alias_user;
2238 }
2239 else
2240 return NULL;
2241 }
2242
2243 return pw;
2244 }
2245
2246 static void
2247 init_user_info (void)
2248 {
2249
2250
2251
2252
2253
2254
2255
2256 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
2257 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
2258 DWORD glength = sizeof (gname);
2259 HANDLE token = NULL;
2260 SID_NAME_USE user_type;
2261 unsigned char *buf = NULL;
2262 DWORD blen = 0;
2263 TOKEN_USER user_token;
2264 TOKEN_PRIMARY_GROUP group_token;
2265 BOOL result;
2266
2267 result = open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token);
2268 if (result)
2269 {
2270 result = get_token_information (token, TokenUser, NULL, 0, &blen);
2271 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2272 {
2273 buf = xmalloc (blen);
2274 result = get_token_information (token, TokenUser,
2275 (LPVOID)buf, blen, &needed);
2276 if (result)
2277 {
2278 memcpy (&user_token, buf, sizeof (user_token));
2279 result = lookup_account_sid (NULL, user_token.User.Sid,
2280 uname, &ulength,
2281 domain, &dlength, &user_type);
2282 }
2283 }
2284 else
2285 result = FALSE;
2286 }
2287 if (result)
2288 {
2289 strcpy (dflt_passwd.pw_name, uname);
2290
2291 if (xstrcasecmp ("administrator", uname) == 0)
2292 {
2293 dflt_passwd.pw_uid = 500;
2294 dflt_passwd.pw_gid = 513;
2295 }
2296 else
2297 {
2298
2299
2300 dflt_passwd.pw_uid = get_rid (user_token.User.Sid);
2301
2302
2303 result = get_token_information (token, TokenPrimaryGroup,
2304 (LPVOID)buf, blen, &needed);
2305 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
2306 {
2307 buf = xrealloc (buf, blen = needed);
2308 result = get_token_information (token, TokenPrimaryGroup,
2309 (LPVOID)buf, blen, &needed);
2310 }
2311 if (result)
2312 {
2313 memcpy (&group_token, buf, sizeof (group_token));
2314 dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup);
2315 dlength = sizeof (domain);
2316
2317
2318
2319 if (lookup_account_sid (NULL, group_token.PrimaryGroup,
2320 gname, &glength, NULL, &dlength,
2321 &user_type))
2322 strcpy (dflt_group_name, gname);
2323 }
2324 else
2325 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2326 }
2327 }
2328
2329
2330 else if (GetUserName (uname, &ulength))
2331 {
2332 strcpy (dflt_passwd.pw_name, uname);
2333 if (xstrcasecmp ("administrator", uname) == 0)
2334 dflt_passwd.pw_uid = 0;
2335 else
2336 dflt_passwd.pw_uid = 123;
2337 dflt_passwd.pw_gid = dflt_passwd.pw_uid;
2338 }
2339 else
2340 {
2341 strcpy (dflt_passwd.pw_name, "unknown");
2342 dflt_passwd.pw_uid = 123;
2343 dflt_passwd.pw_gid = 123;
2344 }
2345 dflt_group.gr_gid = dflt_passwd.pw_gid;
2346
2347
2348 if (w32_unicode_filenames)
2349 {
2350 wchar_t *home = _wgetenv (L"HOME");
2351 wchar_t *shell = _wgetenv (L"SHELL");
2352
2353
2354 if (home == NULL)
2355 emacs_abort ();
2356 if (shell == NULL)
2357 emacs_abort ();
2358 filename_from_utf16 (home, dflt_passwd.pw_dir);
2359 filename_from_utf16 (shell, dflt_passwd.pw_shell);
2360 }
2361 else
2362 {
2363 char *home = getenv ("HOME");
2364 char *shell = getenv ("SHELL");
2365
2366 if (home == NULL)
2367 emacs_abort ();
2368 if (shell == NULL)
2369 emacs_abort ();
2370 filename_from_ansi (home, dflt_passwd.pw_dir);
2371 filename_from_ansi (shell, dflt_passwd.pw_shell);
2372 }
2373
2374 xfree (buf);
2375 if (token)
2376 CloseHandle (token);
2377 }
2378
2379 static HCRYPTPROV w32_crypto_hprov;
2380 static int
2381 w32_init_crypt_random (void)
2382 {
2383 if (!CryptAcquireContext (&w32_crypto_hprov, NULL, NULL, PROV_RSA_FULL,
2384 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2385 {
2386 DebPrint (("CryptAcquireContext failed with error %x\n",
2387 GetLastError ()));
2388 w32_crypto_hprov = 0;
2389 return -1;
2390 }
2391 return 0;
2392 }
2393
2394 int
2395 w32_init_random (void *buf, ptrdiff_t buflen)
2396 {
2397 if (!w32_crypto_hprov)
2398 w32_init_crypt_random ();
2399 if (w32_crypto_hprov)
2400 {
2401 if (CryptGenRandom (w32_crypto_hprov, buflen, (BYTE *)buf))
2402 return 0;
2403 }
2404 return -1;
2405 }
2406
2407
2408
2409
2410
2411
2412 static int ix = 3172, iy = 9814, iz = 20125;
2413 #define RAND_MAX_X 30269
2414 #define RAND_MAX_Y 30307
2415 #define RAND_MAX_Z 30323
2416
2417 static int
2418 rand_as183 (void)
2419 {
2420 ix = (171 * ix) % RAND_MAX_X;
2421 iy = (172 * iy) % RAND_MAX_Y;
2422 iz = (170 * iz) % RAND_MAX_Z;
2423
2424 return (ix + iy + iz) & 0x7fff;
2425 }
2426
2427 int
2428 random (void)
2429 {
2430
2431
2432 #if EMACS_INT_MAX > INT_MAX
2433 return ((rand_as183 () << 30) | (rand_as183 () << 15) | rand_as183 ());
2434 #else
2435 return ((rand_as183 () << 15) | rand_as183 ());
2436 #endif
2437 }
2438
2439 void
2440 srandom (int seed)
2441 {
2442 srand (seed);
2443 ix = rand () % RAND_MAX_X;
2444 iy = rand () % RAND_MAX_Y;
2445 iz = rand () % RAND_MAX_Z;
2446 }
2447
2448
2449
2450
2451
2452
2453
2454 void
2455 explicit_bzero (void *buf, size_t len)
2456 {
2457 #if _WIN32_WINNT >= 0x0501
2458
2459
2460 SecureZeroMemory (buf, len);
2461 #else
2462 memset (buf, 0, len);
2463
2464 asm volatile ("" ::: "memory");
2465 #endif
2466 }
2467
2468
2469
2470
2471 static int
2472 max_filename_mbslen (void)
2473 {
2474 CPINFO cp_info;
2475
2476 codepage_for_filenames (&cp_info);
2477 return cp_info.MaxCharSize;
2478 }
2479
2480
2481
2482
2483 static void
2484 normalize_filename (register char *fp, char path_sep)
2485 {
2486 char *p2;
2487
2488
2489
2490
2491
2492
2493 p2 = fp + 1;
2494
2495 if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
2496 {
2497 *fp += 'a' - 'A';
2498 fp += 2;
2499 }
2500
2501 while (*fp)
2502 {
2503 if ((*fp == '/' || *fp == '\\') && *fp != path_sep)
2504 *fp = path_sep;
2505 fp++;
2506 }
2507 }
2508
2509
2510 void
2511 dostounix_filename (register char *p)
2512 {
2513 normalize_filename (p, '/');
2514 }
2515
2516
2517 void
2518 unixtodos_filename (register char *p)
2519 {
2520 normalize_filename (p, '\\');
2521 }
2522
2523
2524
2525
2526 static int
2527 crlf_to_lf (register int n, register char *buf)
2528 {
2529 unsigned char *np = (unsigned char *)buf;
2530 unsigned char *startp = np;
2531 char *endp = buf + n;
2532
2533 if (n == 0)
2534 return n;
2535 while (buf < endp - 1)
2536 {
2537 if (*buf == 0x0d)
2538 {
2539 if (*(++buf) != 0x0a)
2540 *np++ = 0x0d;
2541 }
2542 else
2543 *np++ = *buf++;
2544 }
2545 if (buf < endp)
2546 *np++ = *buf++;
2547 return np - startp;
2548 }
2549
2550
2551
2552 static int
2553 parse_root (const char * name, const char ** pPath)
2554 {
2555 const char * start = name;
2556
2557 if (name == NULL)
2558 return 0;
2559
2560
2561 if (isalpha (name[0]) && name[1] == ':')
2562 {
2563
2564 name += 2;
2565 if (IS_DIRECTORY_SEP (name[0]))
2566 name++;
2567 }
2568 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
2569 {
2570 int slashes = 2;
2571
2572 name += 2;
2573 do
2574 {
2575 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2576 break;
2577 name++;
2578 }
2579 while ( *name );
2580 if (IS_DIRECTORY_SEP (name[0]))
2581 name++;
2582 }
2583
2584 if (pPath)
2585 *pPath = name;
2586
2587 return name - start;
2588 }
2589
2590
2591 static int
2592 get_long_basename (char * name, char * buf, int size)
2593 {
2594 HANDLE dir_handle = INVALID_HANDLE_VALUE;
2595 char fname_utf8[MAX_UTF8_PATH];
2596 int len = 0;
2597 int cstatus = -1;
2598
2599
2600 if (strpbrk (name, "*?|<>\""))
2601 return 0;
2602
2603 if (w32_unicode_filenames)
2604 {
2605 wchar_t fname_utf16[MAX_PATH];
2606 WIN32_FIND_DATAW find_data_wide;
2607
2608 filename_to_utf16 (name, fname_utf16);
2609 dir_handle = FindFirstFileW (fname_utf16, &find_data_wide);
2610 if (dir_handle != INVALID_HANDLE_VALUE)
2611 cstatus = filename_from_utf16 (find_data_wide.cFileName, fname_utf8);
2612 }
2613 else
2614 {
2615 char fname_ansi[MAX_PATH];
2616 WIN32_FIND_DATAA find_data_ansi;
2617
2618 filename_to_ansi (name, fname_ansi);
2619
2620
2621
2622
2623
2624 if (_mbspbrk (fname_ansi, "?"))
2625 {
2626
2627 char *p = strrchr (fname_ansi, '\\');
2628
2629 if (!p)
2630 p = fname_ansi;
2631 else
2632 p++;
2633 cstatus = filename_from_ansi (p, fname_utf8);
2634 }
2635 else
2636 {
2637 dir_handle = FindFirstFileA (fname_ansi, &find_data_ansi);
2638 if (dir_handle != INVALID_HANDLE_VALUE)
2639 cstatus = filename_from_ansi (find_data_ansi.cFileName, fname_utf8);
2640 }
2641 }
2642
2643 if (cstatus == 0 && (len = strlen (fname_utf8)) < size)
2644 memcpy (buf, fname_utf8, len + 1);
2645 else
2646 len = 0;
2647
2648 if (dir_handle != INVALID_HANDLE_VALUE)
2649 FindClose (dir_handle);
2650
2651 return len;
2652 }
2653
2654
2655 BOOL
2656 w32_get_long_filename (const char * name, char * buf, int size)
2657 {
2658 char * o = buf;
2659 char * p;
2660 const char * q;
2661 char full[ MAX_UTF8_PATH ];
2662 int len;
2663
2664 len = strlen (name);
2665 if (len >= MAX_UTF8_PATH)
2666 return FALSE;
2667
2668
2669 memcpy (full, name, len+1);
2670 unixtodos_filename (full);
2671
2672
2673 len = parse_root (full, (const char **)&p);
2674 memcpy (o, full, len);
2675 o += len;
2676 *o = '\0';
2677 size -= len;
2678
2679 while (p != NULL && *p)
2680 {
2681 q = p;
2682 p = strchr (q, '\\');
2683 if (p) *p = '\0';
2684 len = get_long_basename (full, o, size);
2685 if (len > 0)
2686 {
2687 o += len;
2688 size -= len;
2689 if (p != NULL)
2690 {
2691 *p++ = '\\';
2692 if (size < 2)
2693 return FALSE;
2694 *o++ = '\\';
2695 size--;
2696 *o = '\0';
2697 }
2698 }
2699 else
2700 return FALSE;
2701 }
2702
2703 return TRUE;
2704 }
2705
2706 unsigned int
2707 w32_get_short_filename (const char * name, char * buf, int size)
2708 {
2709 if (w32_unicode_filenames)
2710 {
2711 wchar_t name_utf16[MAX_PATH], short_name[MAX_PATH];
2712 unsigned int retval;
2713
2714 filename_to_utf16 (name, name_utf16);
2715 retval = GetShortPathNameW (name_utf16, short_name, size);
2716 if (retval && retval < size)
2717 filename_from_utf16 (short_name, buf);
2718 return retval;
2719 }
2720 else
2721 {
2722 char name_ansi[MAX_PATH];
2723
2724 filename_to_ansi (name, name_ansi);
2725 return GetShortPathNameA (name_ansi, buf, size);
2726 }
2727 }
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737 Lisp_Object
2738 ansi_encode_filename (Lisp_Object filename)
2739 {
2740 Lisp_Object encoded_filename;
2741 char fname[MAX_PATH];
2742
2743 filename_to_ansi (SSDATA (filename), fname);
2744 if (_mbspbrk (fname, "?"))
2745 {
2746 char shortname[MAX_PATH];
2747
2748 if (w32_get_short_filename (SSDATA (filename), shortname, MAX_PATH))
2749 {
2750 dostounix_filename (shortname);
2751 encoded_filename = build_string (shortname);
2752 }
2753 else
2754 encoded_filename = build_unibyte_string (fname);
2755 }
2756 else
2757 encoded_filename = build_unibyte_string (fname);
2758 return encoded_filename;
2759 }
2760
2761 static int
2762 is_unc_volume (const char *filename)
2763 {
2764 const char *ptr = filename;
2765
2766 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
2767 return 0;
2768
2769 if (strpbrk (ptr + 2, "*?|<>\"\\/"))
2770 return 0;
2771
2772 return 1;
2773 }
2774
2775
2776 int
2777 unsetenv (const char *name)
2778 {
2779 char *var;
2780 size_t name_len;
2781
2782 if (name == NULL || *name == '\0' || strchr (name, '=') != NULL)
2783 {
2784 errno = EINVAL;
2785 return -1;
2786 }
2787 name_len = strlen (name);
2788
2789 if (name_len > 32767)
2790 {
2791 errno = ENOMEM;
2792 return 0;
2793 }
2794
2795
2796 var = alloca (name_len + 2);
2797 memcpy (var, name, name_len);
2798 var[name_len++] = '=';
2799 var[name_len] = '\0';
2800 return _putenv (var);
2801 }
2802
2803
2804
2805 int
2806 sys_putenv (char *str)
2807 {
2808 const char *const name_end = strchr (str, '=');
2809
2810 if (name_end == NULL)
2811 {
2812
2813 return unsetenv (str);
2814 }
2815
2816 if (strncmp (str, "TZ=<", 4) == 0)
2817 {
2818
2819
2820
2821 bool supported_abbr = true;
2822 for (char *p = str + 4; *p; p++)
2823 {
2824 if (('0' <= *p && *p <= '9') || *p == '-' || *p == '+')
2825 supported_abbr = false;
2826 else if (*p == '>')
2827 {
2828 ptrdiff_t abbrlen;
2829 if (supported_abbr)
2830 {
2831 abbrlen = p - (str + 4);
2832 memmove (str + 3, str + 4, abbrlen);
2833 }
2834 else
2835 {
2836 abbrlen = 3;
2837 memset (str + 3, 'Z', abbrlen);
2838 }
2839 memmove (str + 3 + abbrlen, p + 1, strlen (p));
2840 break;
2841 }
2842 }
2843 }
2844
2845 return _putenv (str);
2846 }
2847
2848 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
2849
2850
2851
2852 void
2853 init_environment (char ** argv)
2854 {
2855 static const char * const tempdirs[] = {
2856 "$TMPDIR", "$TEMP", "$TMP", "c:/"
2857 };
2858
2859 int i;
2860
2861 const int imax = ARRAYELTS (tempdirs);
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874 for (i = 0; i < imax ; i++)
2875 {
2876 const char *tmp = tempdirs[i];
2877
2878 if (*tmp == '$')
2879 tmp = getenv (tmp + 1);
2880
2881
2882
2883
2884
2885
2886 if (tmp && sys_access (tmp, D_OK) == 0)
2887 {
2888 char * var = alloca (strlen (tmp) + 8);
2889 sprintf (var, "TMPDIR=%s", tmp);
2890 _putenv (strdup (var));
2891 break;
2892 }
2893 }
2894 if (i >= imax)
2895 cmd_error_internal
2896 (Fcons (Qerror,
2897 Fcons (build_string ("no usable temporary directories found!!"),
2898 Qnil)),
2899 "While setting TMPDIR: ");
2900
2901
2902
2903 {
2904 int i;
2905 LPBYTE lpval;
2906 DWORD dwType;
2907 char locale_name[32];
2908 char default_home[MAX_PATH];
2909 int appdata = 0;
2910
2911 static const struct env_entry
2912 {
2913 const char * name;
2914 const char * def_value;
2915 } dflt_envvars[] =
2916 {
2917
2918
2919
2920
2921 {"HOME", "C:/"},
2922 {"PRELOAD_WINSOCK", NULL},
2923 {"emacs_dir", "C:/emacs"},
2924 {"EMACSLOADPATH", NULL},
2925 {"SHELL", "cmdproxy.exe"},
2926 {"EMACSDATA", NULL},
2927 {"EMACSPATH", NULL},
2928 {"INFOPATH", NULL},
2929 {"EMACSDOC", NULL},
2930 {"TERM", "cmd"},
2931 {"LANG", NULL},
2932 };
2933
2934 #define N_ENV_VARS ARRAYELTS (dflt_envvars)
2935
2936
2937
2938
2939
2940 struct env_entry env_vars[N_ENV_VARS];
2941
2942 for (i = 0; i < N_ENV_VARS; i++)
2943 env_vars[i] = dflt_envvars[i];
2944
2945
2946
2947
2948 if (sys_access ("C:/.emacs", F_OK) != 0)
2949 {
2950 HRESULT profile_result;
2951
2952
2953
2954 ShGetFolderPath_fn get_folder_path;
2955 get_folder_path = (ShGetFolderPath_fn)
2956 get_proc_addr (GetModuleHandle ("shell32.dll"),
2957 "SHGetFolderPathA");
2958
2959 if (get_folder_path != NULL)
2960 {
2961 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
2962 0, default_home);
2963
2964
2965 if (profile_result == S_OK)
2966 {
2967 env_vars[0].def_value = default_home;
2968 appdata = 1;
2969 }
2970 }
2971 }
2972
2973
2974 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
2975 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
2976 locale_name, sizeof (locale_name)))
2977 {
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988 if (strcmp (locale_name, "ZZZ") == 0)
2989 {
2990 LANGID lang_id = get_user_default_ui_language ();
2991
2992 if (lang_id != 0)
2993 {
2994
2995 LCID def_lcid = MAKELCID (lang_id, SORT_DEFAULT);
2996 char locale_name_def[32];
2997
2998 if (GetLocaleInfo (def_lcid,
2999 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
3000 locale_name_def, sizeof (locale_name_def)))
3001 strcpy (locale_name, locale_name_def);
3002 }
3003 }
3004 for (i = 0; i < N_ENV_VARS; i++)
3005 {
3006 if (strcmp (env_vars[i].name, "LANG") == 0)
3007 {
3008 env_vars[i].def_value = locale_name;
3009 break;
3010 }
3011 }
3012 }
3013
3014 #define SET_ENV_BUF_SIZE (4 * MAX_PATH)
3015
3016
3017
3018 {
3019 char *p;
3020 char modname[MAX_PATH];
3021
3022 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
3023 emacs_abort ();
3024 if ((p = _mbsrchr (modname, '\\')) == NULL)
3025 emacs_abort ();
3026 *p = 0;
3027
3028 if ((p = _mbsrchr (modname, '\\'))
3029
3030 && (xstrcasecmp (p, "\\bin") == 0 || xstrcasecmp (p, "\\src") == 0))
3031 {
3032 char buf[SET_ENV_BUF_SIZE];
3033 int within_build_tree = xstrcasecmp (p, "\\src") == 0;
3034
3035 *p = 0;
3036 for (p = modname; *p; p = CharNext (p))
3037 if (*p == '\\') *p = '/';
3038
3039 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
3040 _putenv (strdup (buf));
3041
3042
3043
3044 if (within_build_tree)
3045 {
3046 _snprintf (buf, sizeof (buf) - 1,
3047 "SHELL=%s/nt/cmdproxy.exe", modname);
3048 _putenv (strdup (buf));
3049 }
3050 }
3051 }
3052
3053 for (i = 0; i < N_ENV_VARS; i++)
3054 {
3055 if (!getenv (env_vars[i].name))
3056 {
3057 int dont_free = 0;
3058 char bufc[SET_ENV_BUF_SIZE];
3059
3060 if ((lpval = w32_get_resource (REG_ROOT, env_vars[i].name, &dwType)) == NULL
3061
3062 || *lpval == 0)
3063 {
3064 xfree (lpval);
3065 dont_free = 1;
3066 if (strcmp (env_vars[i].name, "SHELL") == 0)
3067 {
3068
3069
3070
3071 char fname[MAX_PATH];
3072 const char *pstart = PATH_EXEC, *pend;
3073
3074 do {
3075 pend = _mbschr (pstart, ';');
3076 if (!pend)
3077 pend = pstart + strlen (pstart);
3078
3079 if (pend > pstart)
3080 {
3081 strncpy (fname, pstart, pend - pstart);
3082 fname[pend - pstart] = '/';
3083 strcpy (&fname[pend - pstart + 1], "cmdproxy.exe");
3084 ExpandEnvironmentStrings ((LPSTR) fname, bufc,
3085 sizeof (bufc));
3086 if (sys_access (bufc, F_OK) == 0)
3087 {
3088 lpval = bufc;
3089 dwType = REG_SZ;
3090 break;
3091 }
3092 }
3093 if (*pend)
3094 pstart = pend + 1;
3095 else
3096 pstart = pend;
3097 if (!*pstart)
3098 {
3099
3100
3101 lpval = (char *)env_vars[i].def_value;
3102 dwType = REG_EXPAND_SZ;
3103 }
3104 } while (*pstart);
3105 }
3106 else
3107 {
3108 lpval = (char *)env_vars[i].def_value;
3109 dwType = REG_EXPAND_SZ;
3110 }
3111 if (strcmp (env_vars[i].name, "HOME") == 0 && !appdata)
3112 Vdelayed_warnings_list
3113 = Fcons
3114 (list2 (intern ("initialization"), build_string
3115 ("Use of `C:\\.emacs' without defining `HOME'\n"
3116 "in the environment is deprecated, "
3117 "see `Windows HOME' in the Emacs manual.")),
3118 Vdelayed_warnings_list);
3119 }
3120
3121 if (lpval)
3122 {
3123 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
3124
3125 if (dwType == REG_EXPAND_SZ)
3126 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof (buf1));
3127 else if (dwType == REG_SZ)
3128 strcpy (buf1, (char *)lpval);
3129 if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
3130 {
3131 _snprintf (buf2, sizeof (buf2)-1, "%s=%s", env_vars[i].name,
3132 buf1);
3133 _putenv (strdup (buf2));
3134 }
3135
3136 if (!dont_free)
3137 xfree (lpval);
3138 }
3139 }
3140 }
3141 }
3142
3143
3144 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155 {
3156 char ** envp;
3157 const char *path = "PATH=";
3158 int path_len = strlen (path);
3159 const char *comspec = "COMSPEC=";
3160 int comspec_len = strlen (comspec);
3161
3162 for (envp = environ; *envp; envp++)
3163 if (_strnicmp (*envp, path, path_len) == 0)
3164 memcpy (*envp, path, path_len);
3165 else if (_strnicmp (*envp, comspec, comspec_len) == 0)
3166 memcpy (*envp, comspec, comspec_len);
3167
3168
3169
3170 for (Lisp_Object env = Vprocess_environment; CONSP (env); env = XCDR (env))
3171 {
3172 Lisp_Object entry = XCAR (env);
3173 if (_strnicmp (SDATA (entry), path, path_len) == 0)
3174 for (int i = 0; i < path_len; i++)
3175 SSET (entry, i, path[i]);
3176 else if (_strnicmp (SDATA (entry), comspec, comspec_len) == 0)
3177 for (int i = 0; i < comspec_len; i++)
3178 SSET (entry, i, comspec[i]);
3179 }
3180 }
3181
3182
3183 w32_get_current_directory (startup_dir);
3184
3185 {
3186 static char modname[MAX_PATH];
3187
3188 if (!GetModuleFileNameA (NULL, modname, MAX_PATH))
3189 emacs_abort ();
3190 argv[0] = modname;
3191 }
3192
3193
3194
3195
3196 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
3197
3198 init_user_info ();
3199 }
3200
3201
3202
3203 char *
3204 emacs_root_dir (void)
3205 {
3206 static char root_dir[MAX_UTF8_PATH];
3207 const char *p;
3208
3209 p = getenv ("emacs_dir");
3210 if (p == NULL)
3211 emacs_abort ();
3212 filename_from_ansi (p, root_dir);
3213 root_dir[parse_root (root_dir, NULL)] = '\0';
3214 dostounix_filename (root_dir);
3215 return root_dir;
3216 }
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229 int
3230 fdutimens (int fd, char const *file, struct timespec const timespec[2])
3231 {
3232 if (!timespec)
3233 {
3234 errno = ENOSYS;
3235 return -1;
3236 }
3237 if (fd < 0 && !file)
3238 {
3239 errno = EBADF;
3240 return -1;
3241 }
3242
3243
3244
3245
3246 if (fd >= 0)
3247 {
3248 struct _utimbuf _ut;
3249
3250 _ut.actime = timespec[0].tv_sec;
3251 _ut.modtime = timespec[1].tv_sec;
3252 return _futime (fd, &_ut);
3253 }
3254 else
3255 return utimensat (fd, file, timespec, 0);
3256 }
3257
3258
3259
3260
3261
3262
3263
3264
3265 char *
3266 sys_ctime (const time_t *t)
3267 {
3268 char *str = (char *) ctime (t);
3269 return (str ? str : (char *)"Sun Jan 01 00:00:00 1970");
3270 }
3271
3272
3273
3274
3275 void
3276 sys_sleep (int seconds)
3277 {
3278 Sleep (seconds * 1000);
3279 }
3280
3281
3282 extern int __cdecl _set_osfhnd (int fd, long h);
3283 extern int __cdecl _free_osfhnd (int fd);
3284
3285
3286 filedesc fd_info [ MAXDESC ];
3287
3288 typedef struct volume_info_data {
3289 struct volume_info_data * next;
3290
3291
3292 DWORD timestamp;
3293
3294
3295 char * root_dir;
3296 DWORD serialnum;
3297 DWORD maxcomp;
3298 DWORD flags;
3299 char * name;
3300 char * type;
3301 } volume_info_data;
3302
3303
3304 static volume_info_data volume_info;
3305
3306
3307
3308 static BOOL fixed_drives[26];
3309
3310
3311
3312 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
3313 #define VOLINFO_STILL_VALID( root_dir, info ) \
3314 ( ( isalpha (root_dir[0]) && \
3315 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
3316 || GetTickCount () - info->timestamp < 10000 )
3317
3318
3319
3320
3321 static volume_info_data *volume_cache = NULL;
3322
3323 static volume_info_data *
3324 lookup_volume_info (char * root_dir)
3325 {
3326 volume_info_data * info;
3327
3328 for (info = volume_cache; info; info = info->next)
3329 if (xstrcasecmp (info->root_dir, root_dir) == 0)
3330 break;
3331 return info;
3332 }
3333
3334 static void
3335 add_volume_info (char * root_dir, volume_info_data * info)
3336 {
3337 info->root_dir = xstrdup (root_dir);
3338 unixtodos_filename (info->root_dir);
3339 info->next = volume_cache;
3340 volume_cache = info;
3341 }
3342
3343
3344
3345
3346
3347 static volume_info_data *
3348 GetCachedVolumeInformation (char * root_dir)
3349 {
3350 volume_info_data * info;
3351 char default_root[ MAX_UTF8_PATH ];
3352 char name[MAX_PATH+1];
3353 char type[MAX_PATH+1];
3354
3355
3356 if (root_dir == NULL)
3357 {
3358 w32_get_current_directory (default_root);
3359 parse_root (default_root, (const char **)&root_dir);
3360 *root_dir = 0;
3361 root_dir = default_root;
3362 }
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376 #if 0
3377
3378
3379
3380
3381
3382
3383 if (isalpha (root_dir[0]) && !fixed[DRIVE_INDEX (root_dir[0])])
3384 {
3385 char remote_name[ 256 ];
3386 char drive[3] = { root_dir[0], ':' };
3387
3388 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
3389 == NO_ERROR)
3390 ;
3391 }
3392 #endif
3393
3394 info = lookup_volume_info (root_dir);
3395
3396 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
3397 {
3398 DWORD serialnum;
3399 DWORD maxcomp;
3400 DWORD flags;
3401
3402
3403 if (w32_unicode_filenames)
3404 {
3405 wchar_t root_w[MAX_PATH];
3406 wchar_t name_w[MAX_PATH+1];
3407 wchar_t type_w[MAX_PATH+1];
3408
3409 filename_to_utf16 (root_dir, root_w);
3410 if (!GetVolumeInformationW (root_w,
3411 name_w, sizeof (name_w),
3412 &serialnum,
3413 &maxcomp,
3414 &flags,
3415 type_w, sizeof (type_w)))
3416 return NULL;
3417
3418
3419 filename_from_utf16 (name_w, name);
3420 filename_from_utf16 (type_w, type);
3421 }
3422 else
3423 {
3424 char root_a[MAX_PATH];
3425 char name_a[MAX_PATH+1];
3426 char type_a[MAX_PATH+1];
3427
3428 filename_to_ansi (root_dir, root_a);
3429 if (!GetVolumeInformationA (root_a,
3430 name_a, sizeof (name_a),
3431 &serialnum,
3432 &maxcomp,
3433 &flags,
3434 type_a, sizeof (type_a)))
3435 return NULL;
3436 filename_from_ansi (name_a, name);
3437 filename_from_ansi (type_a, type);
3438 }
3439
3440
3441
3442 if (info == NULL)
3443 {
3444 info = xmalloc (sizeof (volume_info_data));
3445 add_volume_info (root_dir, info);
3446 }
3447 else
3448 {
3449 xfree (info->name);
3450 xfree (info->type);
3451 }
3452
3453 info->name = xstrdup (name);
3454 unixtodos_filename (info->name);
3455 info->serialnum = serialnum;
3456 info->maxcomp = maxcomp;
3457 info->flags = flags;
3458 info->type = xstrdup (type);
3459 info->timestamp = GetTickCount ();
3460 }
3461
3462 return info;
3463 }
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474 static int
3475 get_volume_info (const char * name, const char ** pPath)
3476 {
3477 char temp[MAX_UTF8_PATH];
3478 char *rootname = NULL;
3479 volume_info_data * info;
3480 int root_len = parse_root (name, pPath);
3481
3482 if (name == NULL)
3483 return FALSE;
3484
3485
3486 if (root_len)
3487 {
3488 strncpy (temp, name, root_len);
3489 temp[root_len] = '\0';
3490 unixtodos_filename (temp);
3491 rootname = temp;
3492 }
3493
3494 info = GetCachedVolumeInformation (rootname);
3495 if (info != NULL)
3496 {
3497
3498 volume_info = *info;
3499 return TRUE;
3500 }
3501 return FALSE;
3502 }
3503
3504
3505
3506
3507 static int
3508 is_fat_volume (const char * name, const char ** pPath)
3509 {
3510 if (get_volume_info (name, pPath))
3511 return (volume_info.maxcomp == 12);
3512 return FALSE;
3513 }
3514
3515
3516
3517
3518 const char *
3519 map_w32_filename (const char * name, const char ** pPath)
3520 {
3521 static char shortname[MAX_UTF8_PATH];
3522 char * str = shortname;
3523 char c;
3524 char * path;
3525 const char * save_name = name;
3526
3527 if (strlen (name) >= sizeof (shortname))
3528 {
3529
3530 strcpy (shortname, "?");
3531 return shortname;
3532 }
3533
3534 if (!fatal_error_in_progress
3535 && is_fat_volume (name, (const char **)&path))
3536 {
3537 register int left = 8;
3538 register int extn = 0;
3539 register int dots = 2;
3540
3541 while (name < path)
3542 *str++ = *name++;
3543
3544 while ((c = *name++))
3545 {
3546 switch ( c )
3547 {
3548 case ':':
3549 case '\\':
3550 case '/':
3551 *str++ = (c == ':' ? ':' : '\\');
3552 extn = 0;
3553 dots = 2;
3554 left = 8;
3555 break;
3556 case '.':
3557 if ( dots )
3558 {
3559
3560
3561
3562
3563 if (! *name ||
3564 *name == '.' ||
3565 IS_DIRECTORY_SEP (*name))
3566 {
3567 *str++ = '.';
3568 dots--;
3569 }
3570 else
3571 {
3572 *str++ = '_';
3573 left--;
3574 dots = 0;
3575 }
3576 }
3577 else if ( !extn )
3578 {
3579 *str++ = '.';
3580 extn = 1;
3581 left = 3;
3582 }
3583 else
3584 {
3585
3586 *str++ = '_';
3587 }
3588 break;
3589 case '~':
3590 case '#':
3591 if ( ! left )
3592 str[-1] = c;
3593
3594 FALLTHROUGH;
3595 default:
3596 if ( left && 'A' <= c && c <= 'Z' )
3597 {
3598 *str++ = tolower (c);
3599 left--;
3600 dots = 0;
3601 }
3602 break;
3603 }
3604 }
3605 *str = '\0';
3606 }
3607 else
3608 {
3609 strcpy (shortname, name);
3610 unixtodos_filename (shortname);
3611 }
3612
3613 if (pPath)
3614 *pPath = shortname + (path - save_name);
3615
3616 return shortname;
3617 }
3618
3619 static int
3620 is_exec (const char * name)
3621 {
3622 char * p = strrchr (name, '.');
3623 return
3624 (p != NULL
3625 && (xstrcasecmp (p, ".exe") == 0 ||
3626 xstrcasecmp (p, ".com") == 0 ||
3627 xstrcasecmp (p, ".bat") == 0 ||
3628 xstrcasecmp (p, ".cmd") == 0));
3629 }
3630
3631
3632
3633
3634
3635
3636
3637 struct dirent dir_static;
3638 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
3639 static int dir_is_fat;
3640 static char dir_pathname[MAX_UTF8_PATH];
3641 static WIN32_FIND_DATAW dir_find_data_w;
3642 static WIN32_FIND_DATAA dir_find_data_a;
3643 #define DIR_FIND_DATA_W 1
3644 #define DIR_FIND_DATA_A 2
3645 static int last_dir_find_data = -1;
3646
3647
3648
3649 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
3650 static HANDLE open_unc_volume (const char *);
3651 static void *read_unc_volume (HANDLE, wchar_t *, char *, int);
3652 static void close_unc_volume (HANDLE);
3653
3654 DIR *
3655 sys_opendir (const char *filename)
3656 {
3657 DIR *dirp;
3658
3659
3660
3661
3662 if (dir_find_handle != INVALID_HANDLE_VALUE)
3663 return NULL;
3664 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3665 return NULL;
3666
3667
3668
3669
3670 if (is_unc_volume (filename))
3671 {
3672 wnet_enum_handle = open_unc_volume (filename);
3673 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
3674 return NULL;
3675 }
3676
3677 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
3678 return NULL;
3679
3680 dirp->dd_fd = 0;
3681 dirp->dd_loc = 0;
3682 dirp->dd_size = 0;
3683
3684 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAX_UTF8_PATH - 1);
3685 dir_pathname[MAX_UTF8_PATH - 1] = '\0';
3686
3687
3688
3689 dir_is_fat = is_fat_volume (filename, NULL);
3690
3691 return dirp;
3692 }
3693
3694 void
3695 sys_closedir (DIR *dirp)
3696 {
3697
3698 if (dir_find_handle != INVALID_HANDLE_VALUE)
3699 {
3700 FindClose (dir_find_handle);
3701 dir_find_handle = INVALID_HANDLE_VALUE;
3702 }
3703 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3704 {
3705 close_unc_volume (wnet_enum_handle);
3706 wnet_enum_handle = INVALID_HANDLE_VALUE;
3707 }
3708 xfree ((char *) dirp);
3709 }
3710
3711 struct dirent *
3712 sys_readdir (DIR *dirp)
3713 {
3714 int downcase = !NILP (Vw32_downcase_file_names);
3715
3716 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
3717 {
3718 if (!read_unc_volume (wnet_enum_handle,
3719 dir_find_data_w.cFileName,
3720 dir_find_data_a.cFileName,
3721 MAX_PATH))
3722 return NULL;
3723 }
3724
3725 else if (dir_find_handle == INVALID_HANDLE_VALUE)
3726 {
3727 char filename[MAX_UTF8_PATH];
3728 int ln;
3729 bool last_slash = true;
3730
3731
3732
3733
3734
3735
3736 strcpy (filename, dir_pathname);
3737 ln = strlen (filename);
3738 if (!IS_DIRECTORY_SEP (filename[ln - 1]))
3739 last_slash = false;
3740
3741
3742
3743
3744 if (w32_unicode_filenames)
3745 {
3746 wchar_t fnw[MAX_PATH + 2];
3747
3748 filename_to_utf16 (filename, fnw);
3749 if (!last_slash)
3750 wcscat (fnw, L"\\");
3751 wcscat (fnw, L"*");
3752 dir_find_handle = FindFirstFileW (fnw, &dir_find_data_w);
3753 }
3754 else
3755 {
3756 char fna[MAX_PATH + 2];
3757
3758 filename_to_ansi (filename, fna);
3759 if (!last_slash)
3760 strcat (fna, "\\");
3761 strcat (fna, "*");
3762
3763
3764
3765 if (_mbspbrk (fna, "?"))
3766 dir_find_handle = INVALID_HANDLE_VALUE;
3767 else
3768 dir_find_handle = FindFirstFileA (fna, &dir_find_data_a);
3769 }
3770
3771 if (dir_find_handle == INVALID_HANDLE_VALUE)
3772 {
3773
3774
3775
3776 switch (GetLastError ())
3777 {
3778
3779
3780
3781
3782
3783 case ERROR_FILE_NOT_FOUND:
3784 errno = 0;
3785
3786 default:
3787 break;
3788 case ERROR_ACCESS_DENIED:
3789 case ERROR_NETWORK_ACCESS_DENIED:
3790 errno = EACCES;
3791 break;
3792 case ERROR_PATH_NOT_FOUND:
3793 case ERROR_INVALID_DRIVE:
3794 case ERROR_NOT_READY:
3795 case ERROR_BAD_NETPATH:
3796 case ERROR_BAD_NET_NAME:
3797 errno = ENOENT;
3798 break;
3799 }
3800 return NULL;
3801 }
3802 }
3803 else if (w32_unicode_filenames)
3804 {
3805 if (!FindNextFileW (dir_find_handle, &dir_find_data_w))
3806 {
3807 errno = 0;
3808 return NULL;
3809 }
3810 }
3811 else
3812 {
3813 if (!FindNextFileA (dir_find_handle, &dir_find_data_a))
3814 {
3815 errno = 0;
3816 return NULL;
3817 }
3818 }
3819
3820
3821
3822 dir_static.d_ino = 1;
3823
3824 if (w32_unicode_filenames)
3825 {
3826 if (downcase || dir_is_fat)
3827 {
3828 wchar_t tem[MAX_PATH];
3829
3830 wcscpy (tem, dir_find_data_w.cFileName);
3831 CharLowerW (tem);
3832 filename_from_utf16 (tem, dir_static.d_name);
3833 }
3834 else
3835 filename_from_utf16 (dir_find_data_w.cFileName, dir_static.d_name);
3836 last_dir_find_data = DIR_FIND_DATA_W;
3837 }
3838 else
3839 {
3840 char tem[MAX_PATH];
3841
3842
3843
3844
3845
3846
3847 if (_mbspbrk (dir_find_data_a.cFileName, "?"))
3848 {
3849 strcpy (tem, dir_find_data_a.cAlternateFileName);
3850
3851
3852 downcase = 1;
3853 }
3854 else if (downcase || dir_is_fat)
3855 strcpy (tem, dir_find_data_a.cFileName);
3856 else
3857 filename_from_ansi (dir_find_data_a.cFileName, dir_static.d_name);
3858 if (downcase || dir_is_fat)
3859 {
3860 _mbslwr (tem);
3861 filename_from_ansi (tem, dir_static.d_name);
3862 }
3863 last_dir_find_data = DIR_FIND_DATA_A;
3864 }
3865
3866 dir_static.d_namlen = strlen (dir_static.d_name);
3867 dir_static.d_reclen = sizeof (struct dirent) - MAX_UTF8_PATH + 3 +
3868 dir_static.d_namlen - dir_static.d_namlen % 4;
3869
3870 return &dir_static;
3871 }
3872
3873 static HANDLE
3874 open_unc_volume (const char *path)
3875 {
3876 const char *fn = map_w32_filename (path, NULL);
3877 DWORD result;
3878 HANDLE henum;
3879
3880 if (w32_unicode_filenames)
3881 {
3882 NETRESOURCEW nrw;
3883 wchar_t fnw[MAX_PATH];
3884
3885 nrw.dwScope = RESOURCE_GLOBALNET;
3886 nrw.dwType = RESOURCETYPE_DISK;
3887 nrw.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3888 nrw.dwUsage = RESOURCEUSAGE_CONTAINER;
3889 nrw.lpLocalName = NULL;
3890 filename_to_utf16 (fn, fnw);
3891 nrw.lpRemoteName = fnw;
3892 nrw.lpComment = NULL;
3893 nrw.lpProvider = NULL;
3894
3895 result = WNetOpenEnumW (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3896 RESOURCEUSAGE_CONNECTABLE, &nrw, &henum);
3897 }
3898 else
3899 {
3900 NETRESOURCEA nra;
3901 char fna[MAX_PATH];
3902
3903 nra.dwScope = RESOURCE_GLOBALNET;
3904 nra.dwType = RESOURCETYPE_DISK;
3905 nra.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
3906 nra.dwUsage = RESOURCEUSAGE_CONTAINER;
3907 nra.lpLocalName = NULL;
3908 filename_to_ansi (fn, fna);
3909 nra.lpRemoteName = fna;
3910 nra.lpComment = NULL;
3911 nra.lpProvider = NULL;
3912
3913 result = WNetOpenEnumA (RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
3914 RESOURCEUSAGE_CONNECTABLE, &nra, &henum);
3915 }
3916 if (result == NO_ERROR)
3917 return henum;
3918 else
3919 {
3920
3921 errno = ENOENT;
3922 return INVALID_HANDLE_VALUE;
3923 }
3924 }
3925
3926 static void *
3927 read_unc_volume (HANDLE henum, wchar_t *fname_w, char *fname_a, int size)
3928 {
3929 DWORD count;
3930 int result;
3931 char *buffer;
3932 DWORD bufsize = 512;
3933 void *retval;
3934
3935 count = 1;
3936 if (w32_unicode_filenames)
3937 {
3938 wchar_t *ptrw;
3939
3940 bufsize *= 2;
3941 buffer = alloca (bufsize);
3942 result = WNetEnumResourceW (henum, &count, buffer, &bufsize);
3943 if (result != NO_ERROR)
3944 return NULL;
3945
3946 ptrw = ((LPNETRESOURCEW) buffer)->lpRemoteName;
3947 ptrw += 2;
3948 while (*ptrw && *ptrw != L'/' && *ptrw != L'\\') ptrw++;
3949 ptrw++;
3950 wcsncpy (fname_w, ptrw, size);
3951 retval = fname_w;
3952 }
3953 else
3954 {
3955 int dbcs_p = max_filename_mbslen () > 1;
3956 char *ptra;
3957
3958 buffer = alloca (bufsize);
3959 result = WNetEnumResourceA (henum, &count, buffer, &bufsize);
3960 if (result != NO_ERROR)
3961 return NULL;
3962 ptra = ((LPNETRESOURCEA) buffer)->lpRemoteName;
3963 ptra += 2;
3964 if (!dbcs_p)
3965 while (*ptra && !IS_DIRECTORY_SEP (*ptra)) ptra++;
3966 else
3967 {
3968 while (*ptra && !IS_DIRECTORY_SEP (*ptra))
3969 ptra = CharNextExA (file_name_codepage, ptra, 0);
3970 }
3971 ptra++;
3972 strncpy (fname_a, ptra, size);
3973 retval = fname_a;
3974 }
3975
3976 return retval;
3977 }
3978
3979 static void
3980 close_unc_volume (HANDLE henum)
3981 {
3982 if (henum != INVALID_HANDLE_VALUE)
3983 WNetCloseEnum (henum);
3984 }
3985
3986 static DWORD
3987 unc_volume_file_attributes (const char *path)
3988 {
3989 HANDLE henum;
3990 DWORD attrs;
3991
3992 henum = open_unc_volume (path);
3993 if (henum == INVALID_HANDLE_VALUE)
3994 return -1;
3995
3996 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
3997
3998 close_unc_volume (henum);
3999
4000 return attrs;
4001 }
4002
4003
4004 static void
4005 logon_network_drive (const char *path)
4006 {
4007 char share[MAX_UTF8_PATH];
4008 int n_slashes;
4009 char drive[4];
4010 UINT drvtype;
4011 char *p;
4012 DWORD val;
4013
4014 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
4015 drvtype = DRIVE_REMOTE;
4016 else if (path[0] == '\0' || path[1] != ':')
4017 drvtype = GetDriveType (NULL);
4018 else
4019 {
4020 drive[0] = path[0];
4021 drive[1] = ':';
4022 drive[2] = '\\';
4023 drive[3] = '\0';
4024 drvtype = GetDriveType (drive);
4025 }
4026
4027
4028 if (drvtype != DRIVE_REMOTE)
4029 return;
4030
4031 n_slashes = 2;
4032 strncpy (share, path, MAX_UTF8_PATH - 1);
4033
4034 for (p = share + 2; *p && p < share + MAX_UTF8_PATH; p++)
4035 {
4036 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
4037 {
4038 *p = '\0';
4039 break;
4040 }
4041 }
4042
4043 if (w32_unicode_filenames)
4044 {
4045 NETRESOURCEW resourcew;
4046 wchar_t share_w[MAX_PATH];
4047
4048 resourcew.dwScope = RESOURCE_GLOBALNET;
4049 resourcew.dwType = RESOURCETYPE_DISK;
4050 resourcew.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
4051 resourcew.dwUsage = RESOURCEUSAGE_CONTAINER;
4052 resourcew.lpLocalName = NULL;
4053 filename_to_utf16 (share, share_w);
4054 resourcew.lpRemoteName = share_w;
4055 resourcew.lpProvider = NULL;
4056
4057 val = WNetAddConnection2W (&resourcew, NULL, NULL, CONNECT_INTERACTIVE);
4058 }
4059 else
4060 {
4061 NETRESOURCEA resourcea;
4062 char share_a[MAX_PATH];
4063
4064 resourcea.dwScope = RESOURCE_GLOBALNET;
4065 resourcea.dwType = RESOURCETYPE_DISK;
4066 resourcea.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
4067 resourcea.dwUsage = RESOURCEUSAGE_CONTAINER;
4068 resourcea.lpLocalName = NULL;
4069 filename_to_ansi (share, share_a);
4070 resourcea.lpRemoteName = share_a;
4071 resourcea.lpProvider = NULL;
4072
4073 val = WNetAddConnection2A (&resourcea, NULL, NULL, CONNECT_INTERACTIVE);
4074 }
4075
4076 switch (val)
4077 {
4078 case NO_ERROR:
4079 case ERROR_ALREADY_ASSIGNED:
4080 break;
4081 case ERROR_ACCESS_DENIED:
4082 case ERROR_LOGON_FAILURE:
4083 errno = EACCES;
4084 break;
4085 case ERROR_BUSY:
4086 errno = EAGAIN;
4087 break;
4088 case ERROR_BAD_NET_NAME:
4089 case ERROR_NO_NET_OR_BAD_PATH:
4090 case ERROR_NO_NETWORK:
4091 case ERROR_CANCELLED:
4092 default:
4093 errno = ENOENT;
4094 break;
4095 }
4096 }
4097
4098
4099 int
4100 faccessat (int dirfd, const char * path, int mode, int flags)
4101 {
4102 DWORD attributes;
4103 char fullname[MAX_UTF8_PATH];
4104
4105
4106
4107
4108 if (dirfd != AT_FDCWD
4109 && !(IS_DIRECTORY_SEP (path[0])
4110 || IS_DEVICE_SEP (path[1])))
4111 {
4112 char lastc = dir_pathname[strlen (dir_pathname) - 1];
4113
4114 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
4115 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", path)
4116 < 0)
4117 {
4118 errno = ENAMETOOLONG;
4119 return -1;
4120 }
4121 path = fullname;
4122 }
4123
4124
4125
4126 if (IS_DIRECTORY_SEP (path[strlen (path) - 1]) && mode == F_OK)
4127 mode |= D_OK;
4128
4129
4130
4131 path = map_w32_filename (path, NULL);
4132
4133
4134
4135
4136 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0
4137 && (flags & AT_SYMLINK_NOFOLLOW) == 0)
4138 path = chase_symlinks (path);
4139
4140 if (w32_unicode_filenames)
4141 {
4142 wchar_t path_w[MAX_PATH];
4143
4144 filename_to_utf16 (path, path_w);
4145 attributes = GetFileAttributesW (path_w);
4146 }
4147 else
4148 {
4149 char path_a[MAX_PATH];
4150
4151 filename_to_ansi (path, path_a);
4152 attributes = GetFileAttributesA (path_a);
4153 }
4154
4155 if (attributes == -1)
4156 {
4157 DWORD w32err = GetLastError ();
4158
4159 switch (w32err)
4160 {
4161 case ERROR_INVALID_NAME:
4162 case ERROR_BAD_PATHNAME:
4163 if (is_unc_volume (path))
4164 {
4165 attributes = unc_volume_file_attributes (path);
4166 if (attributes == -1)
4167 {
4168 errno = EACCES;
4169 return -1;
4170 }
4171 goto check_attrs;
4172 }
4173
4174 FALLTHROUGH;
4175 case ERROR_FILE_NOT_FOUND:
4176 case ERROR_PATH_NOT_FOUND:
4177 case ERROR_INVALID_DRIVE:
4178 case ERROR_NOT_READY:
4179 case ERROR_BAD_NETPATH:
4180 case ERROR_BAD_NET_NAME:
4181 errno = ENOENT;
4182 break;
4183 default:
4184 errno = EACCES;
4185 break;
4186 }
4187 return -1;
4188 }
4189
4190 check_attrs:
4191 if ((mode & X_OK) != 0
4192 && !(is_exec (path) || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
4193 {
4194 errno = EACCES;
4195 return -1;
4196 }
4197 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
4198 {
4199 errno = EACCES;
4200 return -1;
4201 }
4202 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
4203 {
4204 errno = EACCES;
4205 return -1;
4206 }
4207 return 0;
4208 }
4209
4210
4211
4212
4213
4214
4215
4216 int
4217 w32_accessible_directory_p (const char *dirname, ptrdiff_t dirlen)
4218 {
4219 char pattern[MAX_UTF8_PATH];
4220 bool last_slash = dirlen > 0 && IS_DIRECTORY_SEP (dirname[dirlen - 1]);
4221 HANDLE dh;
4222
4223
4224 if (is_unc_volume (dirname))
4225 {
4226 void *read_result = NULL;
4227 wchar_t fnw[MAX_PATH];
4228 char fna[MAX_PATH];
4229
4230 dh = open_unc_volume (dirname);
4231 if (dh != INVALID_HANDLE_VALUE)
4232 {
4233 read_result = read_unc_volume (dh, fnw, fna, MAX_PATH);
4234 close_unc_volume (dh);
4235 }
4236
4237 return read_result != NULL || GetLastError () == ERROR_NO_MORE_ITEMS;
4238 }
4239
4240
4241
4242 strcpy (pattern, map_w32_filename (dirname, NULL));
4243
4244
4245
4246 if (w32_unicode_filenames)
4247 {
4248 wchar_t pat_w[MAX_PATH + 2];
4249 WIN32_FIND_DATAW dfd_w;
4250
4251 filename_to_utf16 (pattern, pat_w);
4252 if (!last_slash)
4253 wcscat (pat_w, L"\\");
4254 wcscat (pat_w, L"*");
4255 dh = FindFirstFileW (pat_w, &dfd_w);
4256 }
4257 else
4258 {
4259 char pat_a[MAX_PATH + 2];
4260 WIN32_FIND_DATAA dfd_a;
4261
4262 filename_to_ansi (pattern, pat_a);
4263 if (!last_slash)
4264 strcpy (pat_a, "\\");
4265 strcat (pat_a, "*");
4266
4267
4268 if (_mbspbrk (pat_a, "?"))
4269 {
4270 errno = ENOENT;
4271 return 0;
4272 }
4273 dh = FindFirstFileA (pat_a, &dfd_a);
4274 }
4275
4276 if (dh == INVALID_HANDLE_VALUE)
4277 {
4278 DWORD w32err = GetLastError ();
4279
4280 switch (w32err)
4281 {
4282 case ERROR_INVALID_NAME:
4283 case ERROR_BAD_PATHNAME:
4284 case ERROR_FILE_NOT_FOUND:
4285 case ERROR_PATH_NOT_FOUND:
4286 case ERROR_NO_MORE_FILES:
4287 case ERROR_BAD_NETPATH:
4288 errno = ENOENT;
4289 break;
4290 case ERROR_NOT_READY:
4291 errno = ENODEV;
4292 break;
4293 default:
4294 errno = EACCES;
4295 break;
4296 }
4297 return 0;
4298 }
4299 FindClose (dh);
4300 return 1;
4301 }
4302
4303
4304
4305
4306
4307
4308
4309 static int
4310 sys_access (const char *fname, int mode)
4311 {
4312 char fname_copy[MAX_PATH], *p;
4313 DWORD attributes;
4314
4315 strcpy (fname_copy, fname);
4316
4317 for (p = fname_copy; *p; p = CharNext (p))
4318 if (*p == '/')
4319 *p = '\\';
4320
4321 if ((attributes = GetFileAttributesA (fname_copy)) == -1)
4322 {
4323 DWORD w32err = GetLastError ();
4324
4325 switch (w32err)
4326 {
4327 case ERROR_INVALID_NAME:
4328 case ERROR_BAD_PATHNAME:
4329 case ERROR_FILE_NOT_FOUND:
4330 case ERROR_BAD_NETPATH:
4331 errno = ENOENT;
4332 break;
4333 default:
4334 errno = EACCES;
4335 break;
4336 }
4337 return -1;
4338 }
4339 if ((mode & X_OK) != 0
4340 && !(is_exec (fname_copy)
4341 || (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0))
4342 {
4343 errno = EACCES;
4344 return -1;
4345 }
4346 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
4347 {
4348 errno = EACCES;
4349 return -1;
4350 }
4351 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
4352 {
4353 errno = EACCES;
4354 return -1;
4355 }
4356 return 0;
4357 }
4358
4359
4360
4361
4362
4363
4364 int
4365 sys_chdir (const char * path)
4366 {
4367 path = map_w32_filename (path, NULL);
4368 if (w32_unicode_filenames)
4369 {
4370 wchar_t newdir_w[MAX_PATH];
4371
4372 if (filename_to_utf16 (path, newdir_w) == 0)
4373 return _wchdir (newdir_w);
4374 return -1;
4375 }
4376 else
4377 {
4378 char newdir_a[MAX_PATH];
4379
4380 if (filename_to_ansi (path, newdir_a) == 0)
4381 return _chdir (newdir_a);
4382 return -1;
4383 }
4384 }
4385
4386 static int
4387 chmod_worker (const char * path, int mode)
4388 {
4389 if (w32_unicode_filenames)
4390 {
4391 wchar_t path_w[MAX_PATH];
4392
4393 filename_to_utf16 (path, path_w);
4394 return _wchmod (path_w, mode);
4395 }
4396 else
4397 {
4398 char path_a[MAX_PATH];
4399
4400 filename_to_ansi (path, path_a);
4401 return _chmod (path_a, mode);
4402 }
4403 }
4404
4405 int
4406 sys_chmod (const char * path, int mode)
4407 {
4408 path = chase_symlinks (map_w32_filename (path, NULL));
4409 return chmod_worker (path, mode);
4410 }
4411
4412 int
4413 lchmod (const char * path, mode_t mode)
4414 {
4415 path = map_w32_filename (path, NULL);
4416 return chmod_worker (path, mode);
4417 }
4418
4419 int
4420 sys_creat (const char * path, int mode)
4421 {
4422 path = map_w32_filename (path, NULL);
4423 if (w32_unicode_filenames)
4424 {
4425 wchar_t path_w[MAX_PATH];
4426
4427 filename_to_utf16 (path, path_w);
4428 return _wcreat (path_w, mode);
4429 }
4430 else
4431 {
4432 char path_a[MAX_PATH];
4433
4434 filename_to_ansi (path, path_a);
4435 return _creat (path_a, mode);
4436 }
4437 }
4438
4439 FILE *
4440 sys_fopen (const char * path, const char * mode)
4441 {
4442 int fd;
4443 int oflag;
4444 const char * mode_save = mode;
4445
4446
4447
4448
4449
4450 if (mode[0] == 'r')
4451 oflag = O_RDONLY;
4452 else if (mode[0] == 'w' || mode[0] == 'a')
4453 oflag = O_WRONLY | O_CREAT | O_TRUNC;
4454 else
4455 return NULL;
4456
4457
4458 while (*++mode)
4459 if (mode[0] == '+')
4460 {
4461 oflag &= ~(O_RDONLY | O_WRONLY);
4462 oflag |= O_RDWR;
4463 }
4464 else if (mode[0] == 'b')
4465 {
4466 oflag &= ~O_TEXT;
4467 oflag |= O_BINARY;
4468 }
4469 else if (mode[0] == 't')
4470 {
4471 oflag &= ~O_BINARY;
4472 oflag |= O_TEXT;
4473 }
4474 else break;
4475
4476 path = map_w32_filename (path, NULL);
4477 if (w32_unicode_filenames)
4478 {
4479 wchar_t path_w[MAX_PATH];
4480
4481 filename_to_utf16 (path, path_w);
4482 fd = _wopen (path_w, oflag | _O_NOINHERIT, 0644);
4483 }
4484 else
4485 {
4486 char path_a[MAX_PATH];
4487
4488 filename_to_ansi (path, path_a);
4489 fd = _open (path_a, oflag | _O_NOINHERIT, 0644);
4490 }
4491 if (fd < 0)
4492 return NULL;
4493
4494 return _fdopen (fd, mode_save);
4495 }
4496
4497
4498 int
4499 sys_link (const char * old, const char * new)
4500 {
4501 HANDLE fileh;
4502 int result = -1;
4503 char oldname[MAX_UTF8_PATH], newname[MAX_UTF8_PATH];
4504 wchar_t oldname_w[MAX_PATH];
4505 char oldname_a[MAX_PATH];
4506
4507 if (old == NULL || new == NULL)
4508 {
4509 errno = ENOENT;
4510 return -1;
4511 }
4512
4513 strcpy (oldname, map_w32_filename (old, NULL));
4514 strcpy (newname, map_w32_filename (new, NULL));
4515
4516 if (w32_unicode_filenames)
4517 {
4518 filename_to_utf16 (oldname, oldname_w);
4519 fileh = CreateFileW (oldname_w, 0, 0, NULL, OPEN_EXISTING,
4520 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4521 }
4522 else
4523 {
4524 filename_to_ansi (oldname, oldname_a);
4525 fileh = CreateFileA (oldname_a, 0, 0, NULL, OPEN_EXISTING,
4526 FILE_FLAG_BACKUP_SEMANTICS, NULL);
4527 }
4528 if (fileh != INVALID_HANDLE_VALUE)
4529 {
4530 int wlen;
4531
4532
4533
4534
4535
4536
4537
4538
4539 struct {
4540 WIN32_STREAM_ID wid;
4541 WCHAR wbuffer[MAX_PATH];
4542 } data;
4543
4544
4545
4546
4547 wlen = pMultiByteToWideChar (CP_UTF8, 0, newname, -1,
4548 data.wid.cStreamName, MAX_PATH);
4549 if (wlen > 0)
4550 {
4551 LPVOID context = NULL;
4552 DWORD wbytes = 0;
4553
4554 data.wid.dwStreamId = BACKUP_LINK;
4555 data.wid.dwStreamAttributes = 0;
4556 data.wid.Size.LowPart = wlen * sizeof (WCHAR);
4557 data.wid.Size.HighPart = 0;
4558 data.wid.dwStreamNameSize = 0;
4559
4560 if (BackupWrite (fileh, (LPBYTE)&data,
4561 offsetof (WIN32_STREAM_ID, cStreamName)
4562 + data.wid.Size.LowPart,
4563 &wbytes, FALSE, FALSE, &context)
4564 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
4565 {
4566
4567 result = 0;
4568 }
4569 else
4570 {
4571 DWORD err = GetLastError ();
4572 DWORD attributes;
4573
4574 switch (err)
4575 {
4576 case ERROR_ACCESS_DENIED:
4577
4578
4579
4580
4581 if (w32_unicode_filenames)
4582 attributes = GetFileAttributesW (oldname_w);
4583 else
4584 attributes = GetFileAttributesA (oldname_a);
4585 if (attributes != -1
4586 && (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
4587 errno = EPERM;
4588 else if (attributes == -1
4589 && is_unc_volume (oldname)
4590 && unc_volume_file_attributes (oldname) != -1)
4591 errno = EPERM;
4592 else
4593 errno = EACCES;
4594 break;
4595 case ERROR_TOO_MANY_LINKS:
4596 errno = EMLINK;
4597 break;
4598 case ERROR_NOT_SAME_DEVICE:
4599 errno = EXDEV;
4600 break;
4601 default:
4602 errno = EINVAL;
4603 break;
4604 }
4605 }
4606 }
4607
4608 CloseHandle (fileh);
4609 }
4610 else
4611 errno = ENOENT;
4612
4613 return result;
4614 }
4615
4616 int
4617 sys_mkdir (const char * path, mode_t mode)
4618 {
4619 path = map_w32_filename (path, NULL);
4620
4621 if (w32_unicode_filenames)
4622 {
4623 wchar_t path_w[MAX_PATH];
4624
4625 filename_to_utf16 (path, path_w);
4626 return _wmkdir (path_w);
4627 }
4628 else
4629 {
4630 char path_a[MAX_PATH];
4631
4632 filename_to_ansi (path, path_a);
4633 return _mkdir (path_a);
4634 }
4635 }
4636
4637 int
4638 sys_open (const char * path, int oflag, int mode)
4639 {
4640 const char* mpath = map_w32_filename (path, NULL);
4641 int res = -1;
4642
4643 if (w32_unicode_filenames)
4644 {
4645 wchar_t mpath_w[MAX_PATH];
4646
4647 filename_to_utf16 (mpath, mpath_w);
4648
4649
4650
4651 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4652 res = _wopen (mpath_w, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4653 if (res < 0)
4654 res = _wopen (mpath_w, oflag | _O_NOINHERIT, mode);
4655 }
4656 else
4657 {
4658 char mpath_a[MAX_PATH];
4659
4660 filename_to_ansi (mpath, mpath_a);
4661 if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
4662 res = _open (mpath_a, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
4663 if (res < 0)
4664 res = _open (mpath_a, oflag | _O_NOINHERIT, mode);
4665 }
4666
4667 return res;
4668 }
4669
4670
4671
4672 #if 0
4673 int
4674 openat (int fd, const char * path, int oflag, int mode)
4675 {
4676
4677
4678 char fullname[MAX_UTF8_PATH];
4679
4680 if (fd != AT_FDCWD)
4681 {
4682 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, path)
4683 < 0)
4684 {
4685 errno = ENAMETOOLONG;
4686 return -1;
4687 }
4688 path = fullname;
4689 }
4690
4691 return sys_open (path, oflag, mode);
4692 }
4693 #endif
4694
4695 int
4696 fchmod (int fd, mode_t mode)
4697 {
4698 return 0;
4699 }
4700
4701 int
4702 fchmodat (int fd, char const *path, mode_t mode, int flags)
4703 {
4704
4705
4706 char fullname[MAX_UTF8_PATH];
4707
4708 if (fd != AT_FDCWD)
4709 {
4710 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, path)
4711 < 0)
4712 {
4713 errno = ENAMETOOLONG;
4714 return -1;
4715 }
4716 path = fullname;
4717 }
4718
4719 return
4720 flags == AT_SYMLINK_NOFOLLOW ? lchmod (path, mode) : sys_chmod (path, mode);
4721 }
4722
4723 int
4724 sys_rename_replace (const char *oldname, const char *newname, BOOL force)
4725 {
4726 BOOL result;
4727 char temp[MAX_UTF8_PATH], temp_a[MAX_PATH];;
4728 int newname_dev;
4729 int oldname_dev;
4730 bool have_temp_a = false;
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745 strcpy (temp, map_w32_filename (oldname, NULL));
4746
4747
4748 oldname_dev = volume_info.serialnum;
4749
4750 if (os_subtype == OS_SUBTYPE_9X)
4751 {
4752 char * o;
4753 char * p;
4754 int i = 0;
4755 char oldname_a[MAX_PATH];
4756
4757 oldname = map_w32_filename (oldname, NULL);
4758 filename_to_ansi (oldname, oldname_a);
4759 filename_to_ansi (temp, temp_a);
4760 if ((o = strrchr (oldname_a, '\\')))
4761 o++;
4762 else
4763 o = (char *) oldname_a;
4764
4765 if ((p = strrchr (temp_a, '\\')))
4766 p++;
4767 else
4768 p = temp_a;
4769
4770 do
4771 {
4772
4773
4774 sprintf (p, "_.%s.%d", o, i);
4775 i++;
4776 result = rename (oldname_a, temp_a);
4777 }
4778
4779 while (result < 0 && errno == EEXIST);
4780 if (result < 0)
4781 return -1;
4782 have_temp_a = true;
4783 }
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796 newname = map_w32_filename (newname, NULL);
4797
4798
4799 newname_dev = volume_info.serialnum;
4800
4801 if (w32_unicode_filenames)
4802 {
4803 wchar_t temp_w[MAX_PATH], newname_w[MAX_PATH];
4804
4805 filename_to_utf16 (temp, temp_w);
4806 filename_to_utf16 (newname, newname_w);
4807 result = _wrename (temp_w, newname_w);
4808 if (result < 0)
4809 {
4810 DWORD w32err = GetLastError ();
4811
4812 if (errno == EACCES
4813 && newname_dev != oldname_dev)
4814 {
4815 DWORD attributes;
4816
4817
4818
4819
4820
4821 if ((attributes = GetFileAttributesW (temp_w)) != -1
4822 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4823 errno = EXDEV;
4824 }
4825 else if (errno == EEXIST && force)
4826 {
4827 DWORD attributes_old;
4828 DWORD attributes_new;
4829
4830 if (_wchmod (newname_w, 0666) != 0)
4831 return result;
4832 attributes_old = GetFileAttributesW (temp_w);
4833 attributes_new = GetFileAttributesW (newname_w);
4834 if (attributes_old != -1 && attributes_new != -1
4835 && ((attributes_old & FILE_ATTRIBUTE_DIRECTORY)
4836 != (attributes_new & FILE_ATTRIBUTE_DIRECTORY)))
4837 {
4838 if ((attributes_old & FILE_ATTRIBUTE_DIRECTORY) != 0)
4839 errno = ENOTDIR;
4840 else
4841 errno = EISDIR;
4842 return -1;
4843 }
4844 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0)
4845 {
4846 if (_wrmdir (newname_w) != 0)
4847 return result;
4848 }
4849 else if (_wunlink (newname_w) != 0)
4850 return result;
4851 result = _wrename (temp_w, newname_w);
4852 }
4853 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4854 && is_symlink (temp))
4855 {
4856
4857
4858
4859 errno = EPERM;
4860 }
4861 }
4862 }
4863 else
4864 {
4865 char newname_a[MAX_PATH];
4866
4867 if (!have_temp_a)
4868 filename_to_ansi (temp, temp_a);
4869 filename_to_ansi (newname, newname_a);
4870 result = rename (temp_a, newname_a);
4871 if (result < 0)
4872 {
4873 DWORD w32err = GetLastError ();
4874
4875 if (errno == EACCES
4876 && newname_dev != oldname_dev)
4877 {
4878 DWORD attributes;
4879 if ((attributes = GetFileAttributesA (temp_a)) != -1
4880 && (attributes & FILE_ATTRIBUTE_DIRECTORY))
4881 errno = EXDEV;
4882 }
4883 else if (errno == EEXIST && force)
4884 {
4885 DWORD attributes_old;
4886 DWORD attributes_new;
4887
4888 if (_chmod (newname_a, 0666) != 0)
4889 return result;
4890 attributes_old = GetFileAttributesA (temp_a);
4891 attributes_new = GetFileAttributesA (newname_a);
4892 if (attributes_old != -1 && attributes_new != -1
4893 && ((attributes_old & FILE_ATTRIBUTE_DIRECTORY)
4894 != (attributes_new & FILE_ATTRIBUTE_DIRECTORY)))
4895 {
4896 if ((attributes_old & FILE_ATTRIBUTE_DIRECTORY) != 0)
4897 errno = ENOTDIR;
4898 else
4899 errno = EISDIR;
4900 return -1;
4901 }
4902 if ((attributes_new & FILE_ATTRIBUTE_DIRECTORY) != 0)
4903 {
4904 if (_rmdir (newname_a) != 0)
4905 return result;
4906 }
4907 else if (_unlink (newname_a) != 0)
4908 return result;
4909 result = rename (temp_a, newname_a);
4910 }
4911 else if (w32err == ERROR_PRIVILEGE_NOT_HELD
4912 && is_symlink (temp))
4913 errno = EPERM;
4914 }
4915 }
4916
4917 return result;
4918 }
4919
4920 int
4921 sys_rename (char const *old, char const *new)
4922 {
4923 return sys_rename_replace (old, new, TRUE);
4924 }
4925
4926 int
4927 sys_rmdir (const char * path)
4928 {
4929 path = map_w32_filename (path, NULL);
4930
4931 if (w32_unicode_filenames)
4932 {
4933 wchar_t path_w[MAX_PATH];
4934
4935 filename_to_utf16 (path, path_w);
4936 return _wrmdir (path_w);
4937 }
4938 else
4939 {
4940 char path_a[MAX_PATH];
4941
4942 filename_to_ansi (path, path_a);
4943 return _rmdir (path_a);
4944 }
4945 }
4946
4947 int
4948 sys_unlink (const char * path)
4949 {
4950 int rmstatus, e;
4951
4952 path = map_w32_filename (path, NULL);
4953
4954 if (w32_unicode_filenames)
4955 {
4956 wchar_t path_w[MAX_PATH];
4957
4958 filename_to_utf16 (path, path_w);
4959
4960 _wchmod (path_w, 0666);
4961 rmstatus = _wunlink (path_w);
4962 e = errno;
4963
4964
4965 if (rmstatus != 0
4966 && errno == EACCES
4967 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4968 rmstatus = _wrmdir (path_w);
4969 else
4970 errno = e;
4971 }
4972 else
4973 {
4974 char path_a[MAX_PATH];
4975
4976 filename_to_ansi (path, path_a);
4977 _chmod (path_a, 0666);
4978 rmstatus = _unlink (path_a);
4979 e = errno;
4980 if (rmstatus != 0
4981 && errno == EACCES
4982 && (is_symlink (path) & FILE_ATTRIBUTE_DIRECTORY) != 0)
4983 rmstatus = _rmdir (path_a);
4984 else
4985 errno = e;
4986 }
4987
4988 return rmstatus;
4989 }
4990
4991 static FILETIME utc_base_ft;
4992 static ULONGLONG utc_base;
4993 static int init = 0;
4994
4995 #define FILETIME_TO_U64(result, ft) \
4996 do { \
4997 ULARGE_INTEGER uiTemp; \
4998 uiTemp.LowPart = (ft).dwLowDateTime; \
4999 uiTemp.HighPart = (ft).dwHighDateTime; \
5000 result = uiTemp.QuadPart; \
5001 } while (0)
5002
5003 static void
5004 initialize_utc_base (void)
5005 {
5006
5007 SYSTEMTIME st;
5008
5009 st.wYear = 1970;
5010 st.wMonth = 1;
5011 st.wDay = 1;
5012 st.wHour = 0;
5013 st.wMinute = 0;
5014 st.wSecond = 0;
5015 st.wMilliseconds = 0;
5016
5017 SystemTimeToFileTime (&st, &utc_base_ft);
5018 FILETIME_TO_U64 (utc_base, utc_base_ft);
5019 }
5020
5021 static time_t
5022 convert_time (FILETIME ft)
5023 {
5024 ULONGLONG tmp;
5025
5026 if (!init)
5027 {
5028 initialize_utc_base ();
5029 init = 1;
5030 }
5031
5032 if (CompareFileTime (&ft, &utc_base_ft) < 0)
5033 return 0;
5034
5035 FILETIME_TO_U64 (tmp, ft);
5036 return (time_t) ((tmp - utc_base) / 10000000L);
5037 }
5038
5039 static void
5040 convert_from_timespec (struct timespec time, FILETIME * pft)
5041 {
5042 ULARGE_INTEGER tmp;
5043
5044 if (!init)
5045 {
5046 initialize_utc_base ();
5047 init = 1;
5048 }
5049
5050
5051 tmp.QuadPart =
5052 (ULONGLONG) time.tv_sec * 10000000L + time.tv_nsec / 100 + utc_base;
5053 pft->dwHighDateTime = tmp.HighPart;
5054 pft->dwLowDateTime = tmp.LowPart;
5055 }
5056
5057 static PSECURITY_DESCRIPTOR
5058 get_file_security_desc_by_handle (HANDLE h)
5059 {
5060 PSECURITY_DESCRIPTOR psd = NULL;
5061 DWORD err;
5062 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
5063 | GROUP_SECURITY_INFORMATION ;
5064
5065 err = get_security_info (h, SE_FILE_OBJECT, si,
5066 NULL, NULL, NULL, NULL, &psd);
5067 if (err != ERROR_SUCCESS)
5068 return NULL;
5069
5070 return psd;
5071 }
5072
5073 static PSECURITY_DESCRIPTOR
5074 get_file_security_desc_by_name (const char *fname)
5075 {
5076 PSECURITY_DESCRIPTOR psd = NULL;
5077 DWORD sd_len, err;
5078 SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
5079 | GROUP_SECURITY_INFORMATION ;
5080
5081 if (!get_file_security (fname, si, psd, 0, &sd_len))
5082 {
5083 err = GetLastError ();
5084 if (err != ERROR_INSUFFICIENT_BUFFER)
5085 return NULL;
5086 }
5087
5088 psd = xmalloc (sd_len);
5089 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
5090 {
5091 xfree (psd);
5092 return NULL;
5093 }
5094
5095 return psd;
5096 }
5097
5098 static DWORD
5099 get_rid (PSID sid)
5100 {
5101 unsigned n_subauthorities;
5102
5103
5104
5105 n_subauthorities = *get_sid_sub_authority_count (sid);
5106 if (n_subauthorities < 1)
5107 return 0;
5108 return *get_sid_sub_authority (sid, n_subauthorities - 1);
5109 }
5110
5111
5112
5113 struct w32_id {
5114 unsigned rid;
5115 struct w32_id *next;
5116 char name[GNLEN+1];
5117 unsigned char sid[FLEXIBLE_ARRAY_MEMBER];
5118 };
5119
5120 static struct w32_id *w32_idlist;
5121
5122 static int
5123 w32_cached_id (PSID sid, unsigned *id, char *name)
5124 {
5125 struct w32_id *tail, *found;
5126
5127 for (found = NULL, tail = w32_idlist; tail; tail = tail->next)
5128 {
5129 if (equal_sid ((PSID)tail->sid, sid))
5130 {
5131 found = tail;
5132 break;
5133 }
5134 }
5135 if (found)
5136 {
5137 *id = found->rid;
5138 strcpy (name, found->name);
5139 return 1;
5140 }
5141 else
5142 return 0;
5143 }
5144
5145 static void
5146 w32_add_to_cache (PSID sid, unsigned id, char *name)
5147 {
5148 DWORD sid_len;
5149 struct w32_id *new_entry;
5150
5151
5152
5153 if (initialized)
5154 {
5155 sid_len = get_length_sid (sid);
5156 new_entry = xmalloc (offsetof (struct w32_id, sid) + sid_len);
5157 if (new_entry)
5158 {
5159 new_entry->rid = id;
5160 strcpy (new_entry->name, name);
5161 copy_sid (sid_len, (PSID)new_entry->sid, sid);
5162 new_entry->next = w32_idlist;
5163 w32_idlist = new_entry;
5164 }
5165 }
5166 }
5167
5168 #define UID 1
5169 #define GID 2
5170
5171 static int
5172 get_name_and_id (PSECURITY_DESCRIPTOR psd, unsigned *id, char *nm, int what)
5173 {
5174 PSID sid = NULL;
5175 BOOL dflt;
5176 SID_NAME_USE ignore;
5177 char name[UNLEN+1];
5178 DWORD name_len = sizeof (name);
5179 char domain[1024];
5180 DWORD domain_len = sizeof (domain);
5181 int use_dflt = 0;
5182 int result;
5183
5184 if (what == UID)
5185 result = get_security_descriptor_owner (psd, &sid, &dflt);
5186 else if (what == GID)
5187 result = get_security_descriptor_group (psd, &sid, &dflt);
5188 else
5189 result = 0;
5190
5191 if (!result || !is_valid_sid (sid))
5192 use_dflt = 1;
5193 else if (!w32_cached_id (sid, id, nm))
5194 {
5195 if (!lookup_account_sid (NULL, sid, name, &name_len,
5196 domain, &domain_len, &ignore)
5197 || name_len > UNLEN+1)
5198 use_dflt = 1;
5199 else
5200 {
5201 *id = get_rid (sid);
5202 strcpy (nm, name);
5203 w32_add_to_cache (sid, *id, name);
5204 }
5205 }
5206 return use_dflt;
5207 }
5208
5209 static void
5210 get_file_owner_and_group (PSECURITY_DESCRIPTOR psd, struct stat *st)
5211 {
5212 int dflt_usr = 0, dflt_grp = 0;
5213
5214 if (!psd)
5215 {
5216 dflt_usr = 1;
5217 dflt_grp = 1;
5218 }
5219 else
5220 {
5221 if (get_name_and_id (psd, &st->st_uid, st->st_uname, UID))
5222 dflt_usr = 1;
5223 if (get_name_and_id (psd, &st->st_gid, st->st_gname, GID))
5224 dflt_grp = 1;
5225 }
5226
5227
5228 if (dflt_usr)
5229 {
5230 st->st_uid = dflt_passwd.pw_uid;
5231 strcpy (st->st_uname, dflt_passwd.pw_name);
5232 }
5233 if (dflt_grp)
5234 {
5235 st->st_gid = dflt_passwd.pw_gid;
5236 strcpy (st->st_gname, dflt_group.gr_name);
5237 }
5238 }
5239
5240
5241 int is_slow_fs (const char *);
5242
5243 int
5244 is_slow_fs (const char *name)
5245 {
5246 char drive_root[4];
5247 UINT devtype;
5248
5249 if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
5250 devtype = DRIVE_REMOTE;
5251 else if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
5252 devtype = GetDriveType (NULL);
5253 else
5254 {
5255
5256 strncpy (drive_root, name, 2);
5257 drive_root[2] = '\\';
5258 drive_root[3] = '\0';
5259 devtype = GetDriveType (drive_root);
5260 }
5261 return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
5262 }
5263
5264
5265
5266
5267 int w32_stat_get_owner_group;
5268
5269
5270
5271
5272
5273
5274 static int
5275 stat_worker (const char * path, struct stat * buf, int follow_symlinks)
5276 {
5277 char *name, *save_name, *r;
5278 WIN32_FIND_DATAW wfd_w;
5279 WIN32_FIND_DATAA wfd_a;
5280 HANDLE fh;
5281 unsigned __int64 fake_inode = 0;
5282 int permission;
5283 int len;
5284 int rootdir = FALSE;
5285 PSECURITY_DESCRIPTOR psd = NULL;
5286 int is_a_symlink = 0;
5287 DWORD file_flags = FILE_FLAG_BACKUP_SEMANTICS;
5288 DWORD access_rights = 0;
5289 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
5290 FILETIME ctime, atime, wtime;
5291 wchar_t name_w[MAX_PATH];
5292 char name_a[MAX_PATH];
5293
5294 if (path == NULL || buf == NULL)
5295 {
5296 errno = EFAULT;
5297 return -1;
5298 }
5299
5300 save_name = name = (char *) map_w32_filename (path, &path);
5301
5302
5303 if (strpbrk (name, "*?|<>\""))
5304 {
5305 errno = ENOENT;
5306 return -1;
5307 }
5308
5309 len = strlen (name);
5310
5311
5312 name = strcpy (alloca (len + 2), name);
5313
5314
5315
5316 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
5317 is_a_symlink = is_symlink (name);
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338 if (!(NILP (Vw32_get_true_file_attributes)
5339 || (EQ (Vw32_get_true_file_attributes, Qlocal) && is_slow_fs (name)))
5340
5341 || (is_a_symlink && follow_symlinks))
5342 {
5343 BY_HANDLE_FILE_INFORMATION info;
5344
5345 if (is_a_symlink && !follow_symlinks)
5346 file_flags |= FILE_FLAG_OPEN_REPARSE_POINT;
5347
5348
5349
5350 if (is_windows_9x () != TRUE)
5351 access_rights |= READ_CONTROL;
5352
5353 if (w32_unicode_filenames)
5354 {
5355 filename_to_utf16 (name, name_w);
5356 fh = CreateFileW (name_w, access_rights, 0, NULL, OPEN_EXISTING,
5357 file_flags, NULL);
5358
5359
5360 if (fh == INVALID_HANDLE_VALUE && access_rights)
5361 fh = CreateFileW (name_w, 0, 0, NULL, OPEN_EXISTING,
5362 file_flags, NULL);
5363 }
5364 else
5365 {
5366 filename_to_ansi (name, name_a);
5367 fh = CreateFileA (name_a, access_rights, 0, NULL, OPEN_EXISTING,
5368 file_flags, NULL);
5369 if (fh == INVALID_HANDLE_VALUE && access_rights)
5370 fh = CreateFileA (name_a, 0, 0, NULL, OPEN_EXISTING,
5371 file_flags, NULL);
5372 }
5373 if (fh == INVALID_HANDLE_VALUE)
5374 goto no_true_file_attributes;
5375
5376
5377
5378
5379 if (GetFileInformationByHandle (fh, &info))
5380 {
5381 nlinks = info.nNumberOfLinks;
5382
5383
5384
5385
5386
5387 fake_inode = info.nFileIndexHigh;
5388 fake_inode <<= 32;
5389 fake_inode += info.nFileIndexLow;
5390 serialnum = info.dwVolumeSerialNumber;
5391 fs_high = info.nFileSizeHigh;
5392 fs_low = info.nFileSizeLow;
5393 ctime = info.ftCreationTime;
5394 atime = info.ftLastAccessTime;
5395 wtime = info.ftLastWriteTime;
5396 fattrs = info.dwFileAttributes;
5397 }
5398 else
5399 {
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415 DWORD w32err = GetLastError ();
5416
5417 switch (w32err)
5418 {
5419 case ERROR_FILE_NOT_FOUND:
5420 errno = ENOENT;
5421 return -1;
5422 }
5423 }
5424
5425
5426
5427
5428 if (is_a_symlink && !follow_symlinks)
5429 buf->st_mode = S_IFLNK;
5430 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5431 buf->st_mode = S_IFDIR;
5432 else
5433 {
5434 DWORD ftype = GetFileType (fh);
5435
5436 switch (ftype)
5437 {
5438 case FILE_TYPE_DISK:
5439 buf->st_mode = S_IFREG;
5440 break;
5441 case FILE_TYPE_PIPE:
5442 buf->st_mode = S_IFIFO;
5443 break;
5444 case FILE_TYPE_CHAR:
5445 case FILE_TYPE_UNKNOWN:
5446 default:
5447 buf->st_mode = S_IFCHR;
5448 }
5449 }
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5463 get_file_owner_and_group (NULL, buf);
5464 else
5465 {
5466 psd = get_file_security_desc_by_handle (fh);
5467 if (psd)
5468 {
5469 get_file_owner_and_group (psd, buf);
5470 LocalFree (psd);
5471 }
5472 else if (!(is_a_symlink && follow_symlinks))
5473 {
5474 psd = get_file_security_desc_by_name (name);
5475 get_file_owner_and_group (psd, buf);
5476 xfree (psd);
5477 }
5478 else
5479 get_file_owner_and_group (NULL, buf);
5480 }
5481 CloseHandle (fh);
5482 }
5483 else
5484 {
5485 no_true_file_attributes:
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499 rootdir = (path >= save_name + len - 1
5500 && (IS_DIRECTORY_SEP (*path) || *path == 0));
5501
5502
5503 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
5504 if (IS_DIRECTORY_SEP (r[0])
5505 && r[1] == '.' && r[2] == '.' && r[3] == '\0')
5506 r[1] = r[2] = '\0';
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516 if (is_unc_volume (name))
5517 {
5518 fattrs = unc_volume_file_attributes (name);
5519 if (fattrs == -1)
5520 return -1;
5521
5522 ctime = atime = wtime = utc_base_ft;
5523 }
5524 else if (rootdir)
5525 {
5526
5527 if (!IS_DIRECTORY_SEP (name[len-1]))
5528 strcpy (name + len, "\\");
5529 if (GetDriveType (name) < 2)
5530 {
5531 errno = ENOENT;
5532 return -1;
5533 }
5534
5535 fattrs = FILE_ATTRIBUTE_DIRECTORY;
5536 ctime = atime = wtime = utc_base_ft;
5537 }
5538 else
5539 {
5540 int have_wfd = -1;
5541
5542
5543
5544 if (IS_DIRECTORY_SEP (name[len-1]))
5545 name[len - 1] = 0;
5546
5547
5548
5549
5550 len = strlen (dir_pathname);
5551 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
5552 len--;
5553 if (dir_find_handle != INVALID_HANDLE_VALUE
5554 && last_dir_find_data != -1
5555 && !(is_a_symlink && follow_symlinks)
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565 && c_strncasecmp (save_name, dir_pathname, len) == 0
5566 && IS_DIRECTORY_SEP (name[len])
5567 && xstrcasecmp (name + len + 1, dir_static.d_name) == 0)
5568 {
5569 have_wfd = last_dir_find_data;
5570
5571 if (last_dir_find_data == DIR_FIND_DATA_W)
5572 wfd_w = dir_find_data_w;
5573 else
5574 wfd_a = dir_find_data_a;
5575 }
5576 else
5577 {
5578 logon_network_drive (name);
5579
5580 if (w32_unicode_filenames)
5581 {
5582 filename_to_utf16 (name, name_w);
5583 fh = FindFirstFileW (name_w, &wfd_w);
5584 have_wfd = DIR_FIND_DATA_W;
5585 }
5586 else
5587 {
5588 filename_to_ansi (name, name_a);
5589
5590
5591
5592
5593
5594
5595 if (_mbspbrk (name_a, "?"))
5596 fh = INVALID_HANDLE_VALUE;
5597 else
5598 fh = FindFirstFileA (name_a, &wfd_a);
5599 have_wfd = DIR_FIND_DATA_A;
5600 }
5601 if (fh == INVALID_HANDLE_VALUE)
5602 {
5603 errno = ENOENT;
5604 return -1;
5605 }
5606 FindClose (fh);
5607 }
5608
5609
5610 if (have_wfd == DIR_FIND_DATA_W)
5611 {
5612 fattrs = wfd_w.dwFileAttributes;
5613 ctime = wfd_w.ftCreationTime;
5614 atime = wfd_w.ftLastAccessTime;
5615 wtime = wfd_w.ftLastWriteTime;
5616 fs_high = wfd_w.nFileSizeHigh;
5617 fs_low = wfd_w.nFileSizeLow;
5618 }
5619 else
5620 {
5621 fattrs = wfd_a.dwFileAttributes;
5622 ctime = wfd_a.ftCreationTime;
5623 atime = wfd_a.ftLastAccessTime;
5624 wtime = wfd_a.ftLastWriteTime;
5625 fs_high = wfd_a.nFileSizeHigh;
5626 fs_low = wfd_a.nFileSizeLow;
5627 }
5628 fake_inode = 0;
5629 nlinks = 1;
5630 serialnum = volume_info.serialnum;
5631 }
5632 if (is_a_symlink && !follow_symlinks)
5633 buf->st_mode = S_IFLNK;
5634 else if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5635 buf->st_mode = S_IFDIR;
5636 else
5637 buf->st_mode = S_IFREG;
5638
5639 get_file_owner_and_group (NULL, buf);
5640 }
5641
5642 buf->st_ino = fake_inode;
5643
5644 buf->st_dev = serialnum;
5645 buf->st_rdev = serialnum;
5646
5647 buf->st_size = fs_high;
5648 buf->st_size <<= 32;
5649 buf->st_size += fs_low;
5650 buf->st_nlink = nlinks;
5651
5652
5653 buf->st_mtime = convert_time (wtime);
5654 buf->st_atime = convert_time (atime);
5655 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5656 buf->st_ctime = convert_time (ctime);
5657 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5658
5659
5660 if (is_a_symlink && !follow_symlinks)
5661 permission = S_IREAD | S_IWRITE | S_IEXEC;
5662 else
5663 {
5664 if (fattrs & FILE_ATTRIBUTE_READONLY)
5665 permission = S_IREAD;
5666 else
5667 permission = S_IREAD | S_IWRITE;
5668
5669 if (fattrs & FILE_ATTRIBUTE_DIRECTORY)
5670 permission |= S_IEXEC;
5671 else if (is_exec (name))
5672 permission |= S_IEXEC;
5673 }
5674
5675 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5676
5677 return 0;
5678 }
5679
5680 int
5681 stat (const char * path, struct stat * buf)
5682 {
5683 return stat_worker (path, buf, 1);
5684 }
5685
5686 int
5687 lstat (const char * path, struct stat * buf)
5688 {
5689 return stat_worker (path, buf, 0);
5690 }
5691
5692 int
5693 fstatat (int fd, char const *name, struct stat *st, int flags)
5694 {
5695
5696
5697
5698
5699
5700 char fullname[MAX_UTF8_PATH];
5701
5702 if (fd != AT_FDCWD)
5703 {
5704 char lastc = dir_pathname[strlen (dir_pathname) - 1];
5705
5706 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
5707 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
5708 < 0)
5709 {
5710 errno = ENAMETOOLONG;
5711 return -1;
5712 }
5713 name = fullname;
5714 }
5715
5716 return stat_worker (name, st, ! (flags & AT_SYMLINK_NOFOLLOW));
5717 }
5718
5719
5720
5721 int
5722 fstat (int desc, struct stat * buf)
5723 {
5724 HANDLE fh = (HANDLE) _get_osfhandle (desc);
5725 BY_HANDLE_FILE_INFORMATION info;
5726 unsigned __int64 fake_inode;
5727 int permission;
5728
5729 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
5730 {
5731 case FILE_TYPE_DISK:
5732 buf->st_mode = S_IFREG;
5733 if (!GetFileInformationByHandle (fh, &info))
5734 {
5735 errno = EACCES;
5736 return -1;
5737 }
5738 break;
5739 case FILE_TYPE_PIPE:
5740 buf->st_mode = S_IFIFO;
5741 goto non_disk;
5742 case FILE_TYPE_CHAR:
5743 case FILE_TYPE_UNKNOWN:
5744 default:
5745 buf->st_mode = S_IFCHR;
5746 non_disk:
5747 memset (&info, 0, sizeof (info));
5748 info.dwFileAttributes = 0;
5749 info.ftCreationTime = utc_base_ft;
5750 info.ftLastAccessTime = utc_base_ft;
5751 info.ftLastWriteTime = utc_base_ft;
5752 }
5753
5754 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5755 buf->st_mode = S_IFDIR;
5756
5757 buf->st_nlink = info.nNumberOfLinks;
5758
5759
5760
5761
5762
5763 fake_inode = info.nFileIndexHigh;
5764 fake_inode <<= 32;
5765 fake_inode += info.nFileIndexLow;
5766
5767
5768 if (sizeof (buf->st_ino) == 2)
5769 buf->st_ino = fake_inode ^ (fake_inode >> 16);
5770 else
5771 buf->st_ino = fake_inode;
5772
5773
5774
5775 if (!w32_stat_get_owner_group || is_windows_9x () == TRUE)
5776 get_file_owner_and_group (NULL, buf);
5777 else
5778 {
5779 PSECURITY_DESCRIPTOR psd = NULL;
5780
5781 psd = get_file_security_desc_by_handle (fh);
5782 if (psd)
5783 {
5784 get_file_owner_and_group (psd, buf);
5785 LocalFree (psd);
5786 }
5787 else
5788 get_file_owner_and_group (NULL, buf);
5789 }
5790
5791 buf->st_dev = info.dwVolumeSerialNumber;
5792 buf->st_rdev = info.dwVolumeSerialNumber;
5793
5794 buf->st_size = info.nFileSizeHigh;
5795 buf->st_size <<= 32;
5796 buf->st_size += info.nFileSizeLow;
5797
5798
5799 buf->st_mtime = convert_time (info.ftLastWriteTime);
5800 buf->st_atime = convert_time (info.ftLastAccessTime);
5801 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
5802 buf->st_ctime = convert_time (info.ftCreationTime);
5803 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
5804
5805
5806 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
5807 permission = S_IREAD;
5808 else
5809 permission = S_IREAD | S_IWRITE;
5810
5811 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
5812 permission |= S_IEXEC;
5813 else
5814 {
5815 #if 0
5816 char * p = strrchr (name, '.');
5817 if (p != NULL &&
5818 (xstrcasecmp (p, ".exe") == 0 ||
5819 xstrcasecmp (p, ".com") == 0 ||
5820 xstrcasecmp (p, ".bat") == 0 ||
5821 xstrcasecmp (p, ".cmd") == 0))
5822 permission |= S_IEXEC;
5823 #endif
5824 }
5825
5826 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
5827
5828 return 0;
5829 }
5830
5831
5832
5833 int
5834 utimensat (int fd, const char *name, const struct timespec times[2], int flag)
5835 {
5836 struct timespec ltimes[2];
5837 HANDLE fh;
5838 FILETIME mtime;
5839 FILETIME atime;
5840 DWORD flags_and_attrs = FILE_FLAG_BACKUP_SEMANTICS;
5841
5842
5843
5844
5845
5846
5847 char fullname[MAX_UTF8_PATH];
5848
5849 if (fd != AT_FDCWD)
5850 {
5851 char lastc = dir_pathname[strlen (dir_pathname) - 1];
5852
5853 if (_snprintf (fullname, sizeof fullname, "%s%s%s",
5854 dir_pathname, IS_DIRECTORY_SEP (lastc) ? "" : "/", name)
5855 < 0)
5856 {
5857 errno = ENAMETOOLONG;
5858 return -1;
5859 }
5860 name = fullname;
5861 }
5862
5863 if (times == NULL)
5864 {
5865 memset (ltimes, 0, sizeof (ltimes));
5866 ltimes[0] = ltimes[1] = current_timespec ();
5867 }
5868 else
5869 {
5870 if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
5871 return 0;
5872 if ((times[0].tv_nsec != UTIME_NOW && times[0].tv_nsec != UTIME_OMIT
5873 && !(0 <= times[0].tv_nsec && times[0].tv_nsec < 1000000000))
5874 || (times[1].tv_nsec != UTIME_NOW && times[1].tv_nsec != UTIME_OMIT
5875 && !(0 <= times[1].tv_nsec && times[1].tv_nsec < 1000000000)))
5876 {
5877 errno = EINVAL;
5878 return -1;
5879 }
5880
5881 memcpy (ltimes, times, sizeof (ltimes));
5882 if (ltimes[0].tv_nsec == UTIME_NOW)
5883 ltimes[0] = current_timespec ();
5884 if (ltimes[1].tv_nsec == UTIME_NOW)
5885 ltimes[1] = current_timespec ();
5886 }
5887
5888 if (flag == AT_SYMLINK_NOFOLLOW)
5889 flags_and_attrs |= FILE_FLAG_OPEN_REPARSE_POINT;
5890 if (w32_unicode_filenames)
5891 {
5892 wchar_t name_utf16[MAX_PATH];
5893
5894 if (filename_to_utf16 (name, name_utf16) != 0)
5895 return -1;
5896
5897
5898 fh = CreateFileW (name_utf16, FILE_WRITE_ATTRIBUTES,
5899
5900
5901
5902 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5903 0, OPEN_EXISTING, flags_and_attrs, NULL);
5904 }
5905 else
5906 {
5907 char name_ansi[MAX_PATH];
5908
5909 if (filename_to_ansi (name, name_ansi) != 0)
5910 return -1;
5911
5912 fh = CreateFileA (name_ansi, FILE_WRITE_ATTRIBUTES,
5913 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
5914 0, OPEN_EXISTING, flags_and_attrs, NULL);
5915 }
5916 if (fh != INVALID_HANDLE_VALUE)
5917 {
5918 FILETIME *patime, *pmtime;
5919 if (ltimes[0].tv_nsec == UTIME_OMIT)
5920 patime = NULL;
5921 else
5922 {
5923 convert_from_timespec (ltimes[0], &atime);
5924 patime = &atime;
5925 }
5926 if (ltimes[1].tv_nsec == UTIME_OMIT)
5927 pmtime = NULL;
5928 else
5929 {
5930 convert_from_timespec (ltimes[1], &mtime);
5931 pmtime = &mtime;
5932 }
5933 if (!SetFileTime (fh, NULL, patime, pmtime))
5934 {
5935 CloseHandle (fh);
5936 errno = EACCES;
5937 return -1;
5938 }
5939 CloseHandle (fh);
5940 }
5941 else
5942 {
5943 DWORD err = GetLastError ();
5944
5945 switch (err)
5946 {
5947 case ERROR_FILE_NOT_FOUND:
5948 case ERROR_PATH_NOT_FOUND:
5949 case ERROR_INVALID_DRIVE:
5950 case ERROR_BAD_NETPATH:
5951 case ERROR_DEV_NOT_EXIST:
5952
5953
5954 case ERROR_INVALID_NAME:
5955 errno = ENOENT;
5956 break;
5957 case ERROR_TOO_MANY_OPEN_FILES:
5958 errno = ENFILE;
5959 break;
5960 case ERROR_ACCESS_DENIED:
5961 case ERROR_SHARING_VIOLATION:
5962 errno = EACCES;
5963 break;
5964 default:
5965 errno = EINVAL;
5966 break;
5967 }
5968 return -1;
5969 }
5970 return 0;
5971 }
5972
5973 int
5974 sys_umask (int mode)
5975 {
5976 static int current_mask;
5977 int retval, arg = 0;
5978
5979
5980
5981
5982
5983
5984 if ((mode & S_IWRITE) != 0)
5985 arg |= S_IWRITE;
5986
5987 retval = _umask (arg);
5988
5989
5990
5991 retval |= (current_mask & ~S_IWRITE);
5992 current_mask = mode;
5993
5994 return retval;
5995 }
5996
5997
5998
5999 #ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
6000 #define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
6001 #endif
6002 #ifndef SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
6003 #define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2
6004 #endif
6005
6006 int
6007 symlink (char const *filename, char const *linkname)
6008 {
6009 char linkfn[MAX_UTF8_PATH], *tgtfn;
6010
6011
6012
6013 DWORD flags =
6014 (os_subtype == OS_SUBTYPE_NT
6015 && (w32_major_version > 10
6016 || (w32_major_version == 10 && w32_build_number >= 14972)))
6017 ? SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE : 0;
6018 int dir_access, filename_ends_in_slash;
6019
6020
6021 if (filename == NULL || linkname == NULL)
6022 {
6023 errno = EFAULT;
6024 return -1;
6025 }
6026 if (!*filename)
6027 {
6028 errno = ENOENT;
6029 return -1;
6030 }
6031 if (strlen (filename) > MAX_UTF8_PATH || strlen (linkname) > MAX_UTF8_PATH)
6032 {
6033 errno = ENAMETOOLONG;
6034 return -1;
6035 }
6036
6037 strcpy (linkfn, map_w32_filename (linkname, NULL));
6038 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0)
6039 {
6040 errno = EPERM;
6041 return -1;
6042 }
6043
6044
6045
6046 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
6047 {
6048
6049
6050
6051
6052
6053
6054
6055 char tem[MAX_UTF8_PATH];
6056 char *p = linkfn + strlen (linkfn);
6057
6058 while (p > linkfn && !IS_ANY_SEP (p[-1]))
6059 p--;
6060 if (p > linkfn)
6061 strncpy (tem, linkfn, p - linkfn);
6062 strcpy (tem + (p - linkfn), filename);
6063 dir_access = faccessat (AT_FDCWD, tem, D_OK, AT_EACCESS);
6064 }
6065 else
6066 dir_access = faccessat (AT_FDCWD, filename, D_OK, AT_EACCESS);
6067
6068
6069
6070
6071
6072
6073 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
6074 if (dir_access == 0 || filename_ends_in_slash)
6075 flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
6076
6077 tgtfn = (char *)map_w32_filename (filename, NULL);
6078 if (filename_ends_in_slash)
6079 tgtfn[strlen (tgtfn) - 1] = '\0';
6080
6081 errno = 0;
6082 if (!create_symbolic_link (linkfn, tgtfn, flags))
6083 {
6084
6085
6086 if (errno != ENOSYS)
6087 {
6088 DWORD w32err = GetLastError ();
6089
6090 switch (w32err)
6091 {
6092
6093
6094 case ERROR_SUCCESS:
6095 case ERROR_FILE_EXISTS:
6096 errno = EEXIST;
6097 break;
6098 case ERROR_ACCESS_DENIED:
6099 errno = EACCES;
6100 break;
6101 case ERROR_FILE_NOT_FOUND:
6102 case ERROR_PATH_NOT_FOUND:
6103 case ERROR_BAD_NETPATH:
6104 case ERROR_INVALID_REPARSE_DATA:
6105 errno = ENOENT;
6106 break;
6107 case ERROR_DIRECTORY:
6108 errno = EISDIR;
6109 break;
6110 case ERROR_PRIVILEGE_NOT_HELD:
6111 case ERROR_NOT_ALL_ASSIGNED:
6112 errno = EPERM;
6113 break;
6114 case ERROR_DISK_FULL:
6115 errno = ENOSPC;
6116 break;
6117 default:
6118 errno = EINVAL;
6119 break;
6120 }
6121 }
6122 return -1;
6123 }
6124 return 0;
6125 }
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140 static int
6141 is_symlink (const char *filename)
6142 {
6143 DWORD attrs;
6144 wchar_t filename_w[MAX_PATH];
6145 char filename_a[MAX_PATH];
6146 WIN32_FIND_DATAW wfdw;
6147 WIN32_FIND_DATAA wfda;
6148 HANDLE fh;
6149 int attrs_mean_symlink;
6150
6151 if (w32_unicode_filenames)
6152 {
6153 filename_to_utf16 (filename, filename_w);
6154 attrs = GetFileAttributesW (filename_w);
6155 }
6156 else
6157 {
6158 filename_to_ansi (filename, filename_a);
6159 attrs = GetFileAttributesA (filename_a);
6160 }
6161 if (attrs == -1)
6162 {
6163 DWORD w32err = GetLastError ();
6164
6165 switch (w32err)
6166 {
6167 case ERROR_BAD_NETPATH:
6168 break;
6169 case ERROR_ACCESS_DENIED:
6170 errno = EACCES;
6171 break;
6172 case ERROR_FILE_NOT_FOUND:
6173 case ERROR_PATH_NOT_FOUND:
6174 default:
6175 errno = ENOENT;
6176 break;
6177 }
6178 return 0;
6179 }
6180 if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
6181 return 0;
6182 logon_network_drive (filename);
6183 if (w32_unicode_filenames)
6184 {
6185 fh = FindFirstFileW (filename_w, &wfdw);
6186 attrs_mean_symlink =
6187 (wfdw.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
6188 && (wfdw.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
6189 if (attrs_mean_symlink)
6190 attrs_mean_symlink |= (wfdw.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
6191 }
6192 else if (_mbspbrk (filename_a, "?"))
6193 {
6194
6195 errno = ENOENT;
6196 return 0;
6197 }
6198 else
6199 {
6200 fh = FindFirstFileA (filename_a, &wfda);
6201 attrs_mean_symlink =
6202 (wfda.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0
6203 && (wfda.dwReserved0 & IO_REPARSE_TAG_SYMLINK) == IO_REPARSE_TAG_SYMLINK;
6204 if (attrs_mean_symlink)
6205 attrs_mean_symlink |= (wfda.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
6206 }
6207 if (fh == INVALID_HANDLE_VALUE)
6208 return 0;
6209 FindClose (fh);
6210 return attrs_mean_symlink;
6211 }
6212
6213
6214
6215
6216
6217
6218
6219 ssize_t
6220 readlink (const char *name, char *buf, size_t buf_size)
6221 {
6222 const char *path;
6223 TOKEN_PRIVILEGES privs;
6224 int restore_privs = 0;
6225 HANDLE sh;
6226 ssize_t retval;
6227 char resolved[MAX_UTF8_PATH];
6228
6229 if (name == NULL)
6230 {
6231 errno = EFAULT;
6232 return -1;
6233 }
6234 if (!*name)
6235 {
6236 errno = ENOENT;
6237 return -1;
6238 }
6239
6240 path = map_w32_filename (name, NULL);
6241
6242 if (strlen (path) > MAX_UTF8_PATH)
6243 {
6244 errno = ENAMETOOLONG;
6245 return -1;
6246 }
6247
6248 errno = 0;
6249 if (is_windows_9x () == TRUE
6250 || (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) == 0
6251 || !is_symlink (path))
6252 {
6253 if (!errno)
6254 errno = EINVAL;
6255 return -1;
6256 }
6257
6258
6259 if (enable_privilege (SE_BACKUP_NAME, TRUE, &privs))
6260 restore_privs = 1;
6261
6262
6263
6264
6265 retval = -1;
6266
6267
6268
6269
6270
6271
6272 if (w32_unicode_filenames)
6273 {
6274 wchar_t path_w[MAX_PATH];
6275
6276 filename_to_utf16 (path, path_w);
6277 sh = CreateFileW (path_w, 0, 0, NULL, OPEN_EXISTING,
6278 FILE_FLAG_OPEN_REPARSE_POINT
6279 | FILE_FLAG_BACKUP_SEMANTICS,
6280 NULL);
6281 }
6282 else
6283 {
6284 char path_a[MAX_PATH];
6285
6286 filename_to_ansi (path, path_a);
6287 sh = CreateFileA (path_a, 0, 0, NULL, OPEN_EXISTING,
6288 FILE_FLAG_OPEN_REPARSE_POINT
6289 | FILE_FLAG_BACKUP_SEMANTICS,
6290 NULL);
6291 }
6292 if (sh != INVALID_HANDLE_VALUE)
6293 {
6294 BYTE reparse_buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
6295 REPARSE_DATA_BUFFER *reparse_data = (REPARSE_DATA_BUFFER *)&reparse_buf[0];
6296 DWORD retbytes;
6297
6298 if (!DeviceIoControl (sh, FSCTL_GET_REPARSE_POINT, NULL, 0,
6299 reparse_buf, MAXIMUM_REPARSE_DATA_BUFFER_SIZE,
6300 &retbytes, NULL))
6301 errno = EIO;
6302 else if (reparse_data->ReparseTag != IO_REPARSE_TAG_SYMLINK)
6303 errno = EINVAL;
6304 else
6305 {
6306
6307
6308
6309 WCHAR *lwname;
6310 size_t lname_size;
6311 USHORT lwname_len =
6312 reparse_data->SymbolicLinkReparseBuffer.PrintNameLength;
6313 WCHAR *lwname_src =
6314 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
6315 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
6316 size_t size_to_copy = buf_size;
6317
6318
6319
6320 lwname = alloca ((lwname_len + 1) * sizeof(WCHAR));
6321 memcpy (lwname, lwname_src, lwname_len);
6322 lwname[lwname_len/sizeof(WCHAR)] = 0;
6323 filename_from_utf16 (lwname, resolved);
6324 dostounix_filename (resolved);
6325 lname_size = strlen (resolved) + 1;
6326 if (lname_size <= buf_size)
6327 size_to_copy = lname_size;
6328 memcpy (buf, resolved, size_to_copy);
6329
6330 retval = size_to_copy;
6331 }
6332 CloseHandle (sh);
6333 }
6334 else
6335 {
6336
6337 DWORD w32err2 = GetLastError ();
6338
6339 switch (w32err2)
6340 {
6341 case ERROR_FILE_NOT_FOUND:
6342 case ERROR_PATH_NOT_FOUND:
6343 errno = ENOENT;
6344 break;
6345 case ERROR_ACCESS_DENIED:
6346 case ERROR_TOO_MANY_OPEN_FILES:
6347 errno = EACCES;
6348 break;
6349 default:
6350 errno = EPERM;
6351 break;
6352 }
6353 }
6354 if (restore_privs)
6355 {
6356 restore_privilege (&privs);
6357 revert_to_self ();
6358 }
6359
6360 return retval;
6361 }
6362
6363 ssize_t
6364 readlinkat (int fd, char const *name, char *buffer,
6365 size_t buffer_size)
6366 {
6367
6368
6369 char fullname[MAX_UTF8_PATH];
6370
6371 if (fd != AT_FDCWD)
6372 {
6373 if (_snprintf (fullname, sizeof fullname, "%s/%s", dir_pathname, name)
6374 < 0)
6375 {
6376 errno = ENAMETOOLONG;
6377 return -1;
6378 }
6379 name = fullname;
6380 }
6381
6382 return readlink (name, buffer, buffer_size);
6383 }
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405 static char *
6406 chase_symlinks (const char *file)
6407 {
6408 static char target[MAX_UTF8_PATH];
6409 char link[MAX_UTF8_PATH];
6410 wchar_t target_w[MAX_PATH], link_w[MAX_PATH];
6411 char target_a[MAX_PATH], link_a[MAX_PATH];
6412 ssize_t res, link_len;
6413 int loop_count = 0;
6414
6415 if (is_windows_9x () == TRUE || !is_symlink (file))
6416 return (char *)file;
6417
6418 if (w32_unicode_filenames)
6419 {
6420 wchar_t file_w[MAX_PATH];
6421
6422 filename_to_utf16 (file, file_w);
6423 if (GetFullPathNameW (file_w, MAX_PATH, link_w, NULL) == 0)
6424 return (char *)file;
6425 filename_from_utf16 (link_w, link);
6426 }
6427 else
6428 {
6429 char file_a[MAX_PATH];
6430
6431 filename_to_ansi (file, file_a);
6432 if (GetFullPathNameA (file_a, MAX_PATH, link_a, NULL) == 0)
6433 return (char *)file;
6434 filename_from_ansi (link_a, link);
6435 }
6436 link_len = strlen (link);
6437
6438 target[0] = '\0';
6439 do {
6440
6441
6442
6443 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
6444 link[link_len--] = '\0';
6445
6446 res = readlink (link, target, MAX_UTF8_PATH);
6447 if (res > 0)
6448 {
6449 target[res] = '\0';
6450 if (!(IS_DEVICE_SEP (target[1])
6451 || (IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))))
6452 {
6453
6454
6455 char *p = link + link_len;
6456
6457 while (p > link && !IS_ANY_SEP (p[-1]))
6458 p--;
6459 strcpy (p, target);
6460 strcpy (target, link);
6461 }
6462
6463
6464 if (w32_unicode_filenames)
6465 {
6466 filename_to_utf16 (target, target_w);
6467 link_len = GetFullPathNameW (target_w, MAX_PATH, link_w, NULL);
6468 if (link_len > 0)
6469 filename_from_utf16 (link_w, link);
6470 }
6471 else
6472 {
6473 filename_to_ansi (target, target_a);
6474 link_len = GetFullPathNameA (target_a, MAX_PATH, link_a, NULL);
6475 if (link_len > 0)
6476 filename_from_ansi (link_a, link);
6477 }
6478 link_len = strlen (link);
6479 }
6480 } while (res > 0 && link_len > 0 && ++loop_count <= 100);
6481
6482 if (loop_count > 100)
6483 errno = ELOOP;
6484
6485 if (target[0] == '\0')
6486 return (char *)file;
6487 return target;
6488 }
6489
6490
6491 bool
6492 symlinks_supported (const char *file)
6493 {
6494 if (is_windows_9x () != TRUE
6495 && get_volume_info (file, NULL)
6496 && (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6497 return true;
6498 return false;
6499 }
6500
6501
6502
6503
6504 int
6505 acl_valid (acl_t acl)
6506 {
6507 return is_valid_security_descriptor ((PSECURITY_DESCRIPTOR)acl) ? 0 : -1;
6508 }
6509
6510 char * ATTRIBUTE_MALLOC
6511 acl_to_text (acl_t acl, ssize_t *size)
6512 {
6513 LPTSTR str_acl;
6514 SECURITY_INFORMATION flags =
6515 OWNER_SECURITY_INFORMATION |
6516 GROUP_SECURITY_INFORMATION |
6517 DACL_SECURITY_INFORMATION;
6518 char *retval = NULL;
6519 ULONG local_size;
6520 int e = errno;
6521
6522 errno = 0;
6523
6524 if (convert_sd_to_sddl ((PSECURITY_DESCRIPTOR)acl, SDDL_REVISION_1, flags, &str_acl, &local_size))
6525 {
6526 errno = e;
6527
6528
6529 retval = xstrdup (str_acl);
6530 if (size)
6531 *size = local_size;
6532 LocalFree (str_acl);
6533 }
6534 else if (errno != ENOTSUP)
6535 errno = EINVAL;
6536
6537 return retval;
6538 }
6539
6540 acl_t
6541 acl_from_text (const char *acl_str)
6542 {
6543 PSECURITY_DESCRIPTOR psd, retval = NULL;
6544 ULONG sd_size;
6545 int e = errno;
6546
6547 errno = 0;
6548
6549 if (convert_sddl_to_sd (acl_str, SDDL_REVISION_1, &psd, &sd_size))
6550 {
6551 errno = e;
6552 retval = xmalloc (sd_size);
6553 memcpy (retval, psd, sd_size);
6554 LocalFree (psd);
6555 }
6556 else if (errno != ENOTSUP)
6557 errno = EINVAL;
6558
6559 return retval;
6560 }
6561
6562 int
6563 acl_free (void *ptr)
6564 {
6565 xfree (ptr);
6566 return 0;
6567 }
6568
6569 acl_t
6570 acl_get_file (const char *fname, acl_type_t type)
6571 {
6572 PSECURITY_DESCRIPTOR psd = NULL;
6573 const char *filename;
6574
6575 if (type == ACL_TYPE_ACCESS)
6576 {
6577 DWORD sd_len, err;
6578 SECURITY_INFORMATION si =
6579 OWNER_SECURITY_INFORMATION |
6580 GROUP_SECURITY_INFORMATION |
6581 DACL_SECURITY_INFORMATION ;
6582 int e = errno;
6583
6584 filename = map_w32_filename (fname, NULL);
6585 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6586 fname = chase_symlinks (filename);
6587 else
6588 fname = filename;
6589
6590 errno = 0;
6591 if (!get_file_security (fname, si, psd, 0, &sd_len)
6592 && errno != ENOTSUP)
6593 {
6594 err = GetLastError ();
6595 if (err == ERROR_INSUFFICIENT_BUFFER)
6596 {
6597 psd = xmalloc (sd_len);
6598 if (!get_file_security (fname, si, psd, sd_len, &sd_len))
6599 {
6600 xfree (psd);
6601 err = GetLastError ();
6602 if (err == ERROR_NOT_SUPPORTED
6603 || err == ERROR_ACCESS_DENIED
6604 || err == ERROR_INVALID_FUNCTION)
6605 errno = ENOTSUP;
6606 else if (err == ERROR_FILE_NOT_FOUND
6607 || err == ERROR_PATH_NOT_FOUND
6608 || err == ERROR_INVALID_NAME)
6609 errno = ENOENT;
6610 else
6611 errno = EIO;
6612 psd = NULL;
6613 }
6614 }
6615 else if (err == ERROR_FILE_NOT_FOUND
6616 || err == ERROR_PATH_NOT_FOUND
6617
6618
6619
6620 || err == ERROR_INVALID_NAME)
6621 errno = ENOENT;
6622 else if (err == ERROR_NOT_SUPPORTED
6623
6624
6625
6626 || err == ERROR_ACCESS_DENIED
6627 || err == ERROR_INVALID_FUNCTION)
6628 errno = ENOTSUP;
6629 else
6630 errno = EIO;
6631 }
6632 else if (!errno)
6633 errno = e;
6634 }
6635 else if (type != ACL_TYPE_DEFAULT)
6636 errno = EINVAL;
6637
6638 return psd;
6639 }
6640
6641 int
6642 acl_set_file (const char *fname, acl_type_t type, acl_t acl)
6643 {
6644 TOKEN_PRIVILEGES old1, old2;
6645 DWORD err;
6646 int st = 0, retval = -1;
6647 SECURITY_INFORMATION flags = 0;
6648 PSID psidOwner, psidGroup;
6649 PACL pacl;
6650 BOOL dflt;
6651 BOOL dacl_present;
6652 int e;
6653 const char *filename;
6654
6655 if (acl_valid (acl) != 0
6656 || (type != ACL_TYPE_DEFAULT && type != ACL_TYPE_ACCESS))
6657 {
6658 errno = EINVAL;
6659 return -1;
6660 }
6661
6662 if (type == ACL_TYPE_DEFAULT)
6663 {
6664 errno = ENOSYS;
6665 return -1;
6666 }
6667
6668 filename = map_w32_filename (fname, NULL);
6669 if ((volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
6670 fname = chase_symlinks (filename);
6671 else
6672 fname = filename;
6673
6674 if (get_security_descriptor_owner ((PSECURITY_DESCRIPTOR)acl, &psidOwner,
6675 &dflt)
6676 && psidOwner)
6677 flags |= OWNER_SECURITY_INFORMATION;
6678 if (get_security_descriptor_group ((PSECURITY_DESCRIPTOR)acl, &psidGroup,
6679 &dflt)
6680 && psidGroup)
6681 flags |= GROUP_SECURITY_INFORMATION;
6682 if (get_security_descriptor_dacl ((PSECURITY_DESCRIPTOR)acl, &dacl_present,
6683 &pacl, &dflt)
6684 && dacl_present)
6685 flags |= DACL_SECURITY_INFORMATION;
6686 if (!flags)
6687 return 0;
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700 if (enable_privilege (SE_TAKE_OWNERSHIP_NAME, TRUE, &old1))
6701 st++;
6702 if (enable_privilege (SE_RESTORE_NAME, TRUE, &old2))
6703 st++;
6704
6705 e = errno;
6706 errno = 0;
6707
6708
6709
6710
6711 if (!set_file_security (fname, flags, (PSECURITY_DESCRIPTOR)acl))
6712 {
6713 err = GetLastError ();
6714
6715 if (errno != ENOTSUP)
6716 err = set_named_security_info (fname, SE_FILE_OBJECT, flags,
6717 psidOwner, psidGroup, pacl, NULL);
6718 }
6719 else
6720 err = ERROR_SUCCESS;
6721 if (err != ERROR_SUCCESS)
6722 {
6723 if (errno == ENOTSUP)
6724 ;
6725 else if (err == ERROR_INVALID_OWNER
6726 || err == ERROR_NOT_ALL_ASSIGNED
6727 || err == ERROR_ACCESS_DENIED)
6728 {
6729
6730
6731
6732 acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
6733
6734 errno = EPERM;
6735 if (current_acl)
6736 {
6737 char *acl_from = acl_to_text (current_acl, NULL);
6738 char *acl_to = acl_to_text (acl, NULL);
6739
6740 if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
6741 {
6742 retval = 0;
6743 errno = e;
6744 }
6745 if (acl_from)
6746 acl_free (acl_from);
6747 if (acl_to)
6748 acl_free (acl_to);
6749 acl_free (current_acl);
6750 }
6751 }
6752 else if (err == ERROR_FILE_NOT_FOUND
6753 || err == ERROR_PATH_NOT_FOUND
6754
6755
6756
6757 || err == ERROR_INVALID_NAME)
6758 errno = ENOENT;
6759 else
6760 errno = EACCES;
6761 }
6762 else
6763 {
6764 retval = 0;
6765 errno = e;
6766 }
6767
6768 if (st)
6769 {
6770 if (st >= 2)
6771 restore_privilege (&old2);
6772 restore_privilege (&old1);
6773 revert_to_self ();
6774 }
6775
6776 return retval;
6777 }
6778
6779
6780
6781
6782 bool
6783 acl_errno_valid (int errnum)
6784 {
6785 switch (errnum)
6786 {
6787 case EBUSY:
6788 case EINVAL:
6789 case ENOTSUP:
6790 return false;
6791 default:
6792 return true;
6793 }
6794 }
6795
6796
6797
6798
6799
6800
6801 char *
6802 careadlinkat (int fd, char const *filename,
6803 char *buffer, size_t buffer_size,
6804 struct allocator const *alloc,
6805 ssize_t (*preadlinkat) (int, char const *, char *, size_t))
6806 {
6807 char linkname[MAX_UTF8_PATH];
6808 ssize_t link_size;
6809
6810 link_size = preadlinkat (fd, filename, linkname, sizeof(linkname));
6811
6812 if (link_size > 0)
6813 {
6814 char *retval = buffer;
6815
6816 linkname[link_size++] = '\0';
6817 if (link_size > buffer_size)
6818 retval = (char *)(alloc ? alloc->allocate : xmalloc) (link_size);
6819 if (retval)
6820 memcpy (retval, linkname, link_size);
6821
6822 return retval;
6823 }
6824 return NULL;
6825 }
6826
6827 int
6828 w32_copy_file (const char *from, const char *to,
6829 int keep_time, int preserve_ownership, int copy_acls)
6830 {
6831 acl_t acl = NULL;
6832 BOOL copy_result;
6833 wchar_t from_w[MAX_PATH], to_w[MAX_PATH];
6834 char from_a[MAX_PATH], to_a[MAX_PATH];
6835
6836
6837 preserve_ownership = preserve_ownership;
6838
6839 if (copy_acls)
6840 {
6841 acl = acl_get_file (from, ACL_TYPE_ACCESS);
6842 if (acl == NULL && acl_errno_valid (errno))
6843 return -2;
6844 }
6845 if (w32_unicode_filenames)
6846 {
6847 filename_to_utf16 (from, from_w);
6848 filename_to_utf16 (to, to_w);
6849 copy_result = CopyFileW (from_w, to_w, FALSE);
6850 }
6851 else
6852 {
6853 filename_to_ansi (from, from_a);
6854 filename_to_ansi (to, to_a);
6855 copy_result = CopyFileA (from_a, to_a, FALSE);
6856 }
6857 if (!copy_result)
6858 {
6859
6860
6861 DWORD err = GetLastError ();
6862
6863 switch (err)
6864 {
6865 case ERROR_FILE_NOT_FOUND:
6866 errno = ENOENT;
6867 break;
6868 case ERROR_ACCESS_DENIED:
6869 errno = EACCES;
6870 break;
6871 case ERROR_ENCRYPTION_FAILED:
6872 errno = EIO;
6873 break;
6874 default:
6875 errno = EPERM;
6876 break;
6877 }
6878
6879 if (acl)
6880 acl_free (acl);
6881 return -1;
6882 }
6883
6884
6885
6886
6887
6888 else if (!keep_time)
6889 {
6890 struct timespec tnow[2];
6891 DWORD attributes;
6892
6893 tnow[0] = tnow[1] = current_timespec ();
6894 if (w32_unicode_filenames)
6895 {
6896
6897 attributes = GetFileAttributesW (to_w);
6898 SetFileAttributesW (to_w, attributes & ~FILE_ATTRIBUTE_READONLY);
6899 if (utimensat (AT_FDCWD, to, tnow, 0))
6900 {
6901
6902 SetFileAttributesW (to_w, attributes);
6903 if (acl)
6904 acl_free (acl);
6905 return -3;
6906 }
6907
6908 SetFileAttributesW (to_w, attributes);
6909 }
6910 else
6911 {
6912 attributes = GetFileAttributesA (to_a);
6913 SetFileAttributesA (to_a, attributes & ~FILE_ATTRIBUTE_READONLY);
6914 if (utimensat (AT_FDCWD, to, tnow, 0))
6915 {
6916 SetFileAttributesA (to_a, attributes);
6917 if (acl)
6918 acl_free (acl);
6919 return -3;
6920 }
6921 SetFileAttributesA (to_a, attributes);
6922 }
6923 }
6924 if (acl != NULL)
6925 {
6926 bool fail =
6927 acl_set_file (to, ACL_TYPE_ACCESS, acl) != 0;
6928 acl_free (acl);
6929 if (fail && acl_errno_valid (errno))
6930 return -4;
6931 }
6932
6933 return 0;
6934 }
6935
6936
6937
6938
6939
6940
6941
6942 static HANDLE WINAPI
6943 create_toolhelp32_snapshot (DWORD Flags, DWORD Ignored)
6944 {
6945 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
6946
6947 if (g_b_init_create_toolhelp32_snapshot == 0)
6948 {
6949 g_b_init_create_toolhelp32_snapshot = 1;
6950 s_pfn_Create_Toolhelp32_Snapshot = (CreateToolhelp32Snapshot_Proc)
6951 get_proc_addr (GetModuleHandle ("kernel32.dll"),
6952 "CreateToolhelp32Snapshot");
6953 }
6954 if (s_pfn_Create_Toolhelp32_Snapshot == NULL)
6955 {
6956 return INVALID_HANDLE_VALUE;
6957 }
6958 return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
6959 }
6960
6961 static BOOL WINAPI
6962 process32_first (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6963 {
6964 static Process32First_Proc s_pfn_Process32_First = NULL;
6965
6966 if (g_b_init_process32_first == 0)
6967 {
6968 g_b_init_process32_first = 1;
6969 s_pfn_Process32_First = (Process32First_Proc)
6970 get_proc_addr (GetModuleHandle ("kernel32.dll"),
6971 "Process32First");
6972 }
6973 if (s_pfn_Process32_First == NULL)
6974 {
6975 return FALSE;
6976 }
6977 return (s_pfn_Process32_First (hSnapshot, lppe));
6978 }
6979
6980 static BOOL WINAPI
6981 process32_next (HANDLE hSnapshot, LPPROCESSENTRY32 lppe)
6982 {
6983 static Process32Next_Proc s_pfn_Process32_Next = NULL;
6984
6985 if (g_b_init_process32_next == 0)
6986 {
6987 g_b_init_process32_next = 1;
6988 s_pfn_Process32_Next = (Process32Next_Proc)
6989 get_proc_addr (GetModuleHandle ("kernel32.dll"),
6990 "Process32Next");
6991 }
6992 if (s_pfn_Process32_Next == NULL)
6993 {
6994 return FALSE;
6995 }
6996 return (s_pfn_Process32_Next (hSnapshot, lppe));
6997 }
6998
6999 static BOOL WINAPI
7000 open_thread_token (HANDLE ThreadHandle,
7001 DWORD DesiredAccess,
7002 BOOL OpenAsSelf,
7003 PHANDLE TokenHandle)
7004 {
7005 static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
7006 HMODULE hm_advapi32 = NULL;
7007 if (is_windows_9x () == TRUE)
7008 {
7009 SetLastError (ERROR_NOT_SUPPORTED);
7010 return FALSE;
7011 }
7012 if (g_b_init_open_thread_token == 0)
7013 {
7014 g_b_init_open_thread_token = 1;
7015 hm_advapi32 = LoadLibrary ("Advapi32.dll");
7016 s_pfn_Open_Thread_Token = (OpenThreadToken_Proc)
7017 get_proc_addr (hm_advapi32, "OpenThreadToken");
7018 }
7019 if (s_pfn_Open_Thread_Token == NULL)
7020 {
7021 SetLastError (ERROR_NOT_SUPPORTED);
7022 return FALSE;
7023 }
7024 return (
7025 s_pfn_Open_Thread_Token (
7026 ThreadHandle,
7027 DesiredAccess,
7028 OpenAsSelf,
7029 TokenHandle)
7030 );
7031 }
7032
7033 static BOOL WINAPI
7034 impersonate_self (SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
7035 {
7036 static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
7037 HMODULE hm_advapi32 = NULL;
7038 if (is_windows_9x () == TRUE)
7039 {
7040 return FALSE;
7041 }
7042 if (g_b_init_impersonate_self == 0)
7043 {
7044 g_b_init_impersonate_self = 1;
7045 hm_advapi32 = LoadLibrary ("Advapi32.dll");
7046 s_pfn_Impersonate_Self = (ImpersonateSelf_Proc)
7047 get_proc_addr (hm_advapi32, "ImpersonateSelf");
7048 }
7049 if (s_pfn_Impersonate_Self == NULL)
7050 {
7051 return FALSE;
7052 }
7053 return s_pfn_Impersonate_Self (ImpersonationLevel);
7054 }
7055
7056 static BOOL WINAPI
7057 revert_to_self (void)
7058 {
7059 static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
7060 HMODULE hm_advapi32 = NULL;
7061 if (is_windows_9x () == TRUE)
7062 {
7063 return FALSE;
7064 }
7065 if (g_b_init_revert_to_self == 0)
7066 {
7067 g_b_init_revert_to_self = 1;
7068 hm_advapi32 = LoadLibrary ("Advapi32.dll");
7069 s_pfn_Revert_To_Self = (RevertToSelf_Proc)
7070 get_proc_addr (hm_advapi32, "RevertToSelf");
7071 }
7072 if (s_pfn_Revert_To_Self == NULL)
7073 {
7074 return FALSE;
7075 }
7076 return s_pfn_Revert_To_Self ();
7077 }
7078
7079 static BOOL WINAPI
7080 get_process_memory_info (HANDLE h_proc,
7081 PPROCESS_MEMORY_COUNTERS mem_counters,
7082 DWORD bufsize)
7083 {
7084 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
7085 HMODULE hm_psapi = NULL;
7086 if (is_windows_9x () == TRUE)
7087 {
7088 return FALSE;
7089 }
7090 if (g_b_init_get_process_memory_info == 0)
7091 {
7092 g_b_init_get_process_memory_info = 1;
7093 hm_psapi = LoadLibrary ("Psapi.dll");
7094 if (hm_psapi)
7095 s_pfn_Get_Process_Memory_Info = (GetProcessMemoryInfo_Proc)
7096 get_proc_addr (hm_psapi, "GetProcessMemoryInfo");
7097 }
7098 if (s_pfn_Get_Process_Memory_Info == NULL)
7099 {
7100 return FALSE;
7101 }
7102 return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
7103 }
7104
7105 static BOOL WINAPI
7106 get_process_working_set_size (HANDLE h_proc,
7107 PSIZE_T minrss,
7108 PSIZE_T maxrss)
7109 {
7110 static GetProcessWorkingSetSize_Proc
7111 s_pfn_Get_Process_Working_Set_Size = NULL;
7112
7113 if (is_windows_9x () == TRUE)
7114 {
7115 return FALSE;
7116 }
7117 if (g_b_init_get_process_working_set_size == 0)
7118 {
7119 g_b_init_get_process_working_set_size = 1;
7120 s_pfn_Get_Process_Working_Set_Size = (GetProcessWorkingSetSize_Proc)
7121 get_proc_addr (GetModuleHandle ("kernel32.dll"),
7122 "GetProcessWorkingSetSize");
7123 }
7124 if (s_pfn_Get_Process_Working_Set_Size == NULL)
7125 {
7126 return FALSE;
7127 }
7128 return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
7129 }
7130
7131 static BOOL WINAPI
7132 global_memory_status (MEMORYSTATUS *buf)
7133 {
7134 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
7135
7136 if (is_windows_9x () == TRUE)
7137 {
7138 return FALSE;
7139 }
7140 if (g_b_init_global_memory_status == 0)
7141 {
7142 g_b_init_global_memory_status = 1;
7143 s_pfn_Global_Memory_Status = (GlobalMemoryStatus_Proc)
7144 get_proc_addr (GetModuleHandle ("kernel32.dll"),
7145 "GlobalMemoryStatus");
7146 }
7147 if (s_pfn_Global_Memory_Status == NULL)
7148 {
7149 return FALSE;
7150 }
7151 return s_pfn_Global_Memory_Status (buf);
7152 }
7153
7154 static BOOL WINAPI
7155 global_memory_status_ex (MEMORY_STATUS_EX *buf)
7156 {
7157 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
7158
7159 if (is_windows_9x () == TRUE)
7160 {
7161 return FALSE;
7162 }
7163 if (g_b_init_global_memory_status_ex == 0)
7164 {
7165 g_b_init_global_memory_status_ex = 1;
7166 s_pfn_Global_Memory_Status_Ex = (GlobalMemoryStatusEx_Proc)
7167 get_proc_addr (GetModuleHandle ("kernel32.dll"),
7168 "GlobalMemoryStatusEx");
7169 }
7170 if (s_pfn_Global_Memory_Status_Ex == NULL)
7171 {
7172 return FALSE;
7173 }
7174 return s_pfn_Global_Memory_Status_Ex (buf);
7175 }
7176
7177 Lisp_Object
7178 list_system_processes (void)
7179 {
7180 Lisp_Object proclist = Qnil;
7181 HANDLE h_snapshot;
7182
7183 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
7184
7185 if (h_snapshot != INVALID_HANDLE_VALUE)
7186 {
7187 PROCESSENTRY32 proc_entry;
7188 DWORD proc_id;
7189 BOOL res;
7190
7191 proc_entry.dwSize = sizeof (PROCESSENTRY32);
7192 for (res = process32_first (h_snapshot, &proc_entry); res;
7193 res = process32_next (h_snapshot, &proc_entry))
7194 {
7195 proc_id = proc_entry.th32ProcessID;
7196 proclist = Fcons (INT_TO_INTEGER (proc_id), proclist);
7197 }
7198
7199 CloseHandle (h_snapshot);
7200 proclist = Fnreverse (proclist);
7201 }
7202
7203 return proclist;
7204 }
7205
7206 static int
7207 enable_privilege (LPCTSTR priv_name, BOOL enable_p, TOKEN_PRIVILEGES *old_priv)
7208 {
7209 TOKEN_PRIVILEGES priv;
7210 DWORD priv_size = sizeof (priv);
7211 DWORD opriv_size = sizeof (*old_priv);
7212 HANDLE h_token = NULL;
7213 HANDLE h_thread = GetCurrentThread ();
7214 int ret_val = 0;
7215 BOOL res;
7216
7217 res = open_thread_token (h_thread,
7218 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
7219 FALSE, &h_token);
7220 if (!res && GetLastError () == ERROR_NO_TOKEN)
7221 {
7222 if (impersonate_self (SecurityImpersonation))
7223 res = open_thread_token (h_thread,
7224 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
7225 FALSE, &h_token);
7226 }
7227 if (res)
7228 {
7229 priv.PrivilegeCount = 1;
7230 priv.Privileges[0].Attributes = enable_p ? SE_PRIVILEGE_ENABLED : 0;
7231 LookupPrivilegeValue (NULL, priv_name, &priv.Privileges[0].Luid);
7232 if (AdjustTokenPrivileges (h_token, FALSE, &priv, priv_size,
7233 old_priv, &opriv_size)
7234 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
7235 ret_val = 1;
7236 }
7237 if (h_token)
7238 CloseHandle (h_token);
7239
7240 return ret_val;
7241 }
7242
7243 static int
7244 restore_privilege (TOKEN_PRIVILEGES *priv)
7245 {
7246 DWORD priv_size = sizeof (*priv);
7247 HANDLE h_token = NULL;
7248 int ret_val = 0;
7249
7250 if (open_thread_token (GetCurrentThread (),
7251 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
7252 FALSE, &h_token))
7253 {
7254 if (AdjustTokenPrivileges (h_token, FALSE, priv, priv_size, NULL, NULL)
7255 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
7256 ret_val = 1;
7257 }
7258 if (h_token)
7259 CloseHandle (h_token);
7260
7261 return ret_val;
7262 }
7263
7264 static Lisp_Object
7265 ltime (ULONGLONG time_100ns)
7266 {
7267 ULONGLONG time_sec = time_100ns / 10000000;
7268 int subsec = time_100ns % 10000000;
7269 return list4i (time_sec >> 16, time_sec & 0xffff,
7270 subsec / 10, subsec % 10 * 100000);
7271 }
7272
7273 #define U64_TO_LISP_TIME(time) ltime (time)
7274
7275 static int
7276 process_times (HANDLE h_proc, Lisp_Object *ctime, Lisp_Object *etime,
7277 Lisp_Object *stime, Lisp_Object *utime, Lisp_Object *ttime,
7278 double *pcpu)
7279 {
7280 FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
7281 ULONGLONG tem1, tem2, tem3, tem;
7282
7283 if (!h_proc
7284 || !get_process_times_fn
7285 || !(*get_process_times_fn) (h_proc, &ft_creation, &ft_exit,
7286 &ft_kernel, &ft_user))
7287 return 0;
7288
7289 GetSystemTimeAsFileTime (&ft_current);
7290
7291 FILETIME_TO_U64 (tem1, ft_kernel);
7292 *stime = U64_TO_LISP_TIME (tem1);
7293
7294 FILETIME_TO_U64 (tem2, ft_user);
7295 *utime = U64_TO_LISP_TIME (tem2);
7296
7297 tem3 = tem1 + tem2;
7298 *ttime = U64_TO_LISP_TIME (tem3);
7299
7300 FILETIME_TO_U64 (tem, ft_creation);
7301
7302 if (tem)
7303 tem -= utc_base;
7304 *ctime = U64_TO_LISP_TIME (tem);
7305
7306 if (tem)
7307 {
7308 FILETIME_TO_U64 (tem3, ft_current);
7309 tem = (tem3 - utc_base) - tem;
7310 }
7311 *etime = U64_TO_LISP_TIME (tem);
7312
7313 if (tem)
7314 {
7315 *pcpu = 100.0 * (tem1 + tem2) / tem;
7316 if (*pcpu > 100)
7317 *pcpu = 100.0;
7318 }
7319 else
7320 *pcpu = 0;
7321
7322 return 1;
7323 }
7324
7325 Lisp_Object
7326 system_process_attributes (Lisp_Object pid)
7327 {
7328 Lisp_Object attrs = Qnil;
7329 Lisp_Object cmd_str, decoded_cmd, tem;
7330 HANDLE h_snapshot, h_proc;
7331 DWORD proc_id;
7332 int found_proc = 0;
7333 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
7334 DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
7335 DWORD glength = sizeof (gname);
7336 HANDLE token = NULL;
7337 SID_NAME_USE user_type;
7338 unsigned char *buf = NULL;
7339 DWORD blen = 0;
7340 TOKEN_USER user_token;
7341 TOKEN_PRIMARY_GROUP group_token;
7342 unsigned euid;
7343 unsigned egid;
7344 PROCESS_MEMORY_COUNTERS mem;
7345 PROCESS_MEMORY_COUNTERS_EX mem_ex;
7346 SIZE_T minrss, maxrss;
7347 MEMORYSTATUS memst;
7348 MEMORY_STATUS_EX memstex;
7349 double totphys = 0.0;
7350 Lisp_Object ctime, stime, utime, etime, ttime;
7351 double pcpu;
7352 BOOL result = FALSE;
7353
7354 CHECK_NUMBER (pid);
7355 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XFIXNUM (pid);
7356
7357 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
7358
7359 if (h_snapshot != INVALID_HANDLE_VALUE)
7360 {
7361 PROCESSENTRY32 pe;
7362 BOOL res;
7363
7364 pe.dwSize = sizeof (PROCESSENTRY32);
7365 for (res = process32_first (h_snapshot, &pe); res;
7366 res = process32_next (h_snapshot, &pe))
7367 {
7368 if (proc_id == pe.th32ProcessID)
7369 {
7370 if (proc_id == 0)
7371 decoded_cmd = build_string ("Idle");
7372 else
7373 {
7374
7375
7376 cmd_str = build_unibyte_string (pe.szExeFile);
7377
7378 decoded_cmd =
7379 code_convert_string_norecord (cmd_str,
7380 Vlocale_coding_system, 0);
7381 }
7382 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
7383 attrs = Fcons (Fcons (Qppid,
7384 INT_TO_INTEGER (pe.th32ParentProcessID)),
7385 attrs);
7386 attrs = Fcons (Fcons (Qpri, make_fixnum (pe.pcPriClassBase)),
7387 attrs);
7388 attrs = Fcons (Fcons (Qthcount,
7389 INT_TO_INTEGER (pe.cntThreads)),
7390 attrs);
7391 found_proc = 1;
7392 break;
7393 }
7394 }
7395
7396 CloseHandle (h_snapshot);
7397 }
7398
7399 if (!found_proc)
7400 return Qnil;
7401
7402 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
7403 FALSE, proc_id);
7404
7405
7406 if (!h_proc)
7407 {
7408 TOKEN_PRIVILEGES priv_current;
7409
7410 if (enable_privilege (SE_DEBUG_NAME, TRUE, &priv_current))
7411 {
7412 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
7413 FALSE, proc_id);
7414 restore_privilege (&priv_current);
7415 revert_to_self ();
7416 }
7417 }
7418 if (h_proc)
7419 {
7420 result = open_process_token (h_proc, TOKEN_QUERY, &token);
7421 if (result)
7422 {
7423 result = get_token_information (token, TokenUser, NULL, 0, &blen);
7424 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
7425 {
7426 buf = xmalloc (blen);
7427 result = get_token_information (token, TokenUser,
7428 (LPVOID)buf, blen, &needed);
7429 if (result)
7430 {
7431 memcpy (&user_token, buf, sizeof (user_token));
7432 if (!w32_cached_id (user_token.User.Sid, &euid, uname))
7433 {
7434 euid = get_rid (user_token.User.Sid);
7435 result = lookup_account_sid (NULL, user_token.User.Sid,
7436 uname, &ulength,
7437 domain, &dlength,
7438 &user_type);
7439 if (result)
7440 w32_add_to_cache (user_token.User.Sid, euid, uname);
7441 else
7442 {
7443 strcpy (uname, "unknown");
7444 result = TRUE;
7445 }
7446 }
7447 ulength = strlen (uname);
7448 }
7449 }
7450 }
7451 if (result)
7452 {
7453
7454 if (xstrcasecmp ("administrator", uname) == 0)
7455 {
7456 euid = 500;
7457 egid = 513;
7458 }
7459 else
7460 {
7461
7462 result = get_token_information (token, TokenPrimaryGroup,
7463 (LPVOID)buf, blen, &needed);
7464 if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
7465 {
7466 buf = xrealloc (buf, blen = needed);
7467 result = get_token_information (token, TokenPrimaryGroup,
7468 (LPVOID)buf, blen, &needed);
7469 }
7470 if (result)
7471 {
7472 memcpy (&group_token, buf, sizeof (group_token));
7473 if (!w32_cached_id (group_token.PrimaryGroup, &egid, gname))
7474 {
7475 egid = get_rid (group_token.PrimaryGroup);
7476 dlength = sizeof (domain);
7477 result =
7478 lookup_account_sid (NULL, group_token.PrimaryGroup,
7479 gname, &glength, NULL, &dlength,
7480 &user_type);
7481 if (result)
7482 w32_add_to_cache (group_token.PrimaryGroup,
7483 egid, gname);
7484 else
7485 {
7486 strcpy (gname, "None");
7487 result = TRUE;
7488 }
7489 }
7490 glength = strlen (gname);
7491 }
7492 }
7493 }
7494 xfree (buf);
7495 }
7496 if (!result)
7497 {
7498 if (!is_windows_9x ())
7499 {
7500
7501
7502
7503 strcpy (uname, "SYSTEM");
7504 strcpy (gname, "None");
7505 euid = 18;
7506 egid = 513;
7507 glength = strlen (gname);
7508 ulength = strlen (uname);
7509 }
7510
7511
7512
7513 else if (GetUserName (uname, &ulength))
7514 {
7515 if (xstrcasecmp ("administrator", uname) == 0)
7516 euid = 0;
7517 else
7518 euid = 123;
7519 egid = euid;
7520 strcpy (gname, "None");
7521 glength = strlen (gname);
7522 ulength = strlen (uname);
7523 }
7524 else
7525 {
7526 euid = 123;
7527 egid = 123;
7528 strcpy (uname, "administrator");
7529 ulength = strlen (uname);
7530 strcpy (gname, "None");
7531 glength = strlen (gname);
7532 }
7533 if (token)
7534 CloseHandle (token);
7535 }
7536
7537 attrs = Fcons (Fcons (Qeuid, INT_TO_INTEGER (euid)), attrs);
7538 tem = make_unibyte_string (uname, ulength);
7539 attrs = Fcons (Fcons (Quser,
7540 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7541 attrs);
7542 attrs = Fcons (Fcons (Qegid, INT_TO_INTEGER (egid)), attrs);
7543 tem = make_unibyte_string (gname, glength);
7544 attrs = Fcons (Fcons (Qgroup,
7545 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
7546 attrs);
7547
7548 memstex.dwLength = sizeof (memstex);
7549 if (global_memory_status_ex (&memstex))
7550 #if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
7551 totphys = memstex.ullTotalPhys / 1024.0;
7552 #else
7553
7554
7555 {
7556 DWORD tot_hi = memstex.ullTotalPhys >> 32;
7557 DWORD tot_md = (memstex.ullTotalPhys & 0x00000000ffffffff) >> 10;
7558 DWORD tot_lo = memstex.ullTotalPhys % 1024;
7559
7560 totphys = tot_hi * 4194304.0 + tot_md + tot_lo / 1024.0;
7561 }
7562 #endif
7563 else if (global_memory_status (&memst))
7564 totphys = memst.dwTotalPhys / 1024.0;
7565
7566 if (h_proc
7567 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
7568 sizeof (mem_ex)))
7569 {
7570 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7571
7572 attrs = Fcons (Fcons (Qmajflt,
7573 INT_TO_INTEGER (mem_ex.PageFaultCount)),
7574 attrs);
7575 attrs = Fcons (Fcons (Qvsize,
7576 INT_TO_INTEGER (mem_ex.PrivateUsage / 1024)),
7577 attrs);
7578 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (rss)), attrs);
7579 if (totphys)
7580 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7581 }
7582 else if (h_proc
7583 && get_process_memory_info (h_proc, &mem, sizeof (mem)))
7584 {
7585 SIZE_T rss = mem_ex.WorkingSetSize / 1024;
7586
7587 attrs = Fcons (Fcons (Qmajflt,
7588 INT_TO_INTEGER (mem.PageFaultCount)),
7589 attrs);
7590 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (rss)), attrs);
7591 if (totphys)
7592 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7593 }
7594 else if (h_proc
7595 && get_process_working_set_size (h_proc, &minrss, &maxrss))
7596 {
7597 DWORD rss = maxrss / 1024;
7598
7599 attrs = Fcons (Fcons (Qrss, INT_TO_INTEGER (maxrss / 1024)), attrs);
7600 if (totphys)
7601 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
7602 }
7603
7604 if (process_times (h_proc, &ctime, &etime, &stime, &utime, &ttime, &pcpu))
7605 {
7606 attrs = Fcons (Fcons (Qutime, utime), attrs);
7607 attrs = Fcons (Fcons (Qstime, stime), attrs);
7608 attrs = Fcons (Fcons (Qtime, ttime), attrs);
7609 attrs = Fcons (Fcons (Qstart, ctime), attrs);
7610 attrs = Fcons (Fcons (Qetime, etime), attrs);
7611 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
7612 }
7613
7614
7615
7616 if (h_proc)
7617 CloseHandle (h_proc);
7618 return attrs;
7619 }
7620
7621 int
7622 w32_memory_info (unsigned long long *totalram, unsigned long long *freeram,
7623 unsigned long long *totalswap, unsigned long long *freeswap)
7624 {
7625 MEMORYSTATUS memst;
7626 MEMORY_STATUS_EX memstex;
7627
7628
7629
7630 if (global_memory_status_ex (&memstex))
7631 {
7632 *totalram = memstex.ullTotalPhys;
7633 *freeram = memstex.ullAvailPhys;
7634 *totalswap = memstex.ullTotalPageFile;
7635 *freeswap = memstex.ullAvailPageFile;
7636 return 0;
7637 }
7638 else if (global_memory_status (&memst))
7639 {
7640 *totalram = memst.dwTotalPhys;
7641 *freeram = memst.dwAvailPhys;
7642 *totalswap = memst.dwTotalPageFile;
7643 *freeswap = memst.dwAvailPageFile;
7644 return 0;
7645 }
7646 else
7647 return -1;
7648 }
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
7661 void (PASCAL *pfn_WSASetLastError) (int iError);
7662 int (PASCAL *pfn_WSAGetLastError) (void);
7663 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
7664 int (PASCAL *pfn_WSAEnumNetworkEvents) (SOCKET s, HANDLE hEventObject,
7665 WSANETWORKEVENTS *NetworkEvents);
7666
7667 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
7668 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
7669 int (PASCAL *pfn_socket) (int af, int type, int protocol);
7670 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
7671 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
7672 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
7673 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
7674 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
7675 int (PASCAL *pfn_closesocket) (SOCKET s);
7676 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
7677 int (PASCAL *pfn_WSACleanup) (void);
7678
7679 u_short (PASCAL *pfn_htons) (u_short hostshort);
7680 u_short (PASCAL *pfn_ntohs) (u_short netshort);
7681 u_long (PASCAL *pfn_htonl) (u_long hostlong);
7682 u_long (PASCAL *pfn_ntohl) (u_long netlong);
7683 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
7684 int (PASCAL *pfn_gethostname) (char * name, int namelen);
7685 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
7686 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
7687 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
7688 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
7689 const char * optval, int optlen);
7690 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
7691 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
7692 int * namelen);
7693 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
7694 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
7695 struct sockaddr * from, int * fromlen);
7696 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
7697 const struct sockaddr * to, int tolen);
7698
7699 int (PASCAL *pfn_getaddrinfo) (const char *, const char *,
7700 const struct addrinfo *, struct addrinfo **);
7701 void (PASCAL *pfn_freeaddrinfo) (struct addrinfo *);
7702
7703
7704 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
7705 #ifndef HANDLE_FLAG_INHERIT
7706 #define HANDLE_FLAG_INHERIT 1
7707 #endif
7708
7709 HANDLE winsock_lib;
7710 static int winsock_inuse;
7711
7712 BOOL term_winsock (void);
7713
7714 BOOL
7715 term_winsock (void)
7716 {
7717 if (winsock_lib != NULL && winsock_inuse == 0)
7718 {
7719 release_listen_threads ();
7720
7721
7722
7723 if (pfn_WSACleanup () == 0 ||
7724 pfn_WSAGetLastError () == WSAENETDOWN)
7725 {
7726 if (FreeLibrary (winsock_lib))
7727 winsock_lib = NULL;
7728 return TRUE;
7729 }
7730 }
7731 return FALSE;
7732 }
7733
7734 BOOL
7735 init_winsock (int load_now)
7736 {
7737 WSADATA winsockData;
7738
7739 if (winsock_lib != NULL)
7740 return TRUE;
7741
7742 pfn_SetHandleInformation
7743 = (void *) get_proc_addr (GetModuleHandle ("kernel32.dll"),
7744 "SetHandleInformation");
7745
7746 winsock_lib = LoadLibrary ("Ws2_32.dll");
7747
7748 if (winsock_lib != NULL)
7749 {
7750
7751
7752 #define LOAD_PROC(fn) \
7753 if ((pfn_##fn = (void *) get_proc_addr (winsock_lib, #fn)) == NULL) \
7754 goto fail;
7755
7756 LOAD_PROC (WSAStartup);
7757 LOAD_PROC (WSASetLastError);
7758 LOAD_PROC (WSAGetLastError);
7759 LOAD_PROC (WSAEventSelect);
7760 LOAD_PROC (WSAEnumNetworkEvents);
7761 LOAD_PROC (WSACreateEvent);
7762 LOAD_PROC (WSACloseEvent);
7763 LOAD_PROC (socket);
7764 LOAD_PROC (bind);
7765 LOAD_PROC (connect);
7766 LOAD_PROC (ioctlsocket);
7767 LOAD_PROC (recv);
7768 LOAD_PROC (send);
7769 LOAD_PROC (closesocket);
7770 LOAD_PROC (shutdown);
7771 LOAD_PROC (htons);
7772 LOAD_PROC (ntohs);
7773 LOAD_PROC (htonl);
7774 LOAD_PROC (ntohl);
7775 LOAD_PROC (inet_addr);
7776 LOAD_PROC (gethostname);
7777 LOAD_PROC (gethostbyname);
7778 LOAD_PROC (getservbyname);
7779 LOAD_PROC (getpeername);
7780 LOAD_PROC (WSACleanup);
7781 LOAD_PROC (setsockopt);
7782 LOAD_PROC (listen);
7783 LOAD_PROC (getsockname);
7784 LOAD_PROC (accept);
7785 LOAD_PROC (recvfrom);
7786 LOAD_PROC (sendto);
7787 #undef LOAD_PROC
7788
7789
7790 pfn_getaddrinfo = (void *) get_proc_addr (winsock_lib, "getaddrinfo");
7791 pfn_freeaddrinfo = (void *) get_proc_addr (winsock_lib, "freeaddrinfo");
7792
7793
7794 if (pfn_getaddrinfo == NULL)
7795 pfn_freeaddrinfo = NULL;
7796 else if (pfn_freeaddrinfo == NULL)
7797 pfn_getaddrinfo = NULL;
7798
7799
7800 if (pfn_WSAStartup (0x101, &winsockData) == 0)
7801 {
7802 if (winsockData.wVersion != 0x101)
7803 goto fail;
7804
7805 if (!load_now)
7806 {
7807
7808
7809
7810
7811
7812
7813 pfn_WSACleanup ();
7814 FreeLibrary (winsock_lib);
7815 winsock_lib = NULL;
7816 }
7817 winsock_inuse = 0;
7818 return TRUE;
7819 }
7820
7821 fail:
7822 FreeLibrary (winsock_lib);
7823 winsock_lib = NULL;
7824 }
7825
7826 return FALSE;
7827 }
7828
7829
7830 int h_errno = 0;
7831
7832
7833
7834
7835 static void
7836 set_errno (void)
7837 {
7838 int wsa_err;
7839
7840 h_errno = 0;
7841 if (winsock_lib == NULL)
7842 wsa_err = EINVAL;
7843 else
7844 wsa_err = pfn_WSAGetLastError ();
7845
7846 switch (wsa_err)
7847 {
7848 case WSAEACCES: errno = EACCES; break;
7849 case WSAEBADF: errno = EBADF; break;
7850 case WSAEFAULT: errno = EFAULT; break;
7851 case WSAEINTR: errno = EINTR; break;
7852 case WSAEINVAL: errno = EINVAL; break;
7853 case WSAEMFILE: errno = EMFILE; break;
7854 case WSAENAMETOOLONG: errno = ENAMETOOLONG; break;
7855 case WSAENOTEMPTY: errno = ENOTEMPTY; break;
7856 case WSAEWOULDBLOCK: errno = EWOULDBLOCK; break;
7857 case WSAENOTCONN: errno = ENOTCONN; break;
7858 default: errno = wsa_err; break;
7859 }
7860 }
7861
7862 static void
7863 check_errno (void)
7864 {
7865 h_errno = 0;
7866 if (winsock_lib != NULL)
7867 pfn_WSASetLastError (0);
7868 }
7869
7870
7871 struct {
7872 int errnum;
7873 const char * msg;
7874 } _wsa_errlist[] = {
7875 {WSAEINTR , "Interrupted function call"},
7876 {WSAEBADF , "Bad file descriptor"},
7877 {WSAEACCES , "Permission denied"},
7878 {WSAEFAULT , "Bad address"},
7879 {WSAEINVAL , "Invalid argument"},
7880 {WSAEMFILE , "Too many open files"},
7881
7882 {WSAEWOULDBLOCK , "Resource temporarily unavailable"},
7883 {WSAEINPROGRESS , "Operation now in progress"},
7884 {WSAEALREADY , "Operation already in progress"},
7885 {WSAENOTSOCK , "Socket operation on non-socket"},
7886 {WSAEDESTADDRREQ , "Destination address required"},
7887 {WSAEMSGSIZE , "Message too long"},
7888 {WSAEPROTOTYPE , "Protocol wrong type for socket"},
7889 {WSAENOPROTOOPT , "Bad protocol option"},
7890 {WSAEPROTONOSUPPORT , "Protocol not supported"},
7891 {WSAESOCKTNOSUPPORT , "Socket type not supported"},
7892 {WSAEOPNOTSUPP , "Operation not supported"},
7893 {WSAEPFNOSUPPORT , "Protocol family not supported"},
7894 {WSAEAFNOSUPPORT , "Address family not supported by protocol family"},
7895 {WSAEADDRINUSE , "Address already in use"},
7896 {WSAEADDRNOTAVAIL , "Cannot assign requested address"},
7897 {WSAENETDOWN , "Network is down"},
7898 {WSAENETUNREACH , "Network is unreachable"},
7899 {WSAENETRESET , "Network dropped connection on reset"},
7900 {WSAECONNABORTED , "Software caused connection abort"},
7901 {WSAECONNRESET , "Connection reset by peer"},
7902 {WSAENOBUFS , "No buffer space available"},
7903 {WSAEISCONN , "Socket is already connected"},
7904 {WSAENOTCONN , "Socket is not connected"},
7905 {WSAESHUTDOWN , "Cannot send after socket shutdown"},
7906 {WSAETOOMANYREFS , "Too many references"},
7907 {WSAETIMEDOUT , "Connection timed out"},
7908 {WSAECONNREFUSED , "Connection refused"},
7909 {WSAELOOP , "Network loop"},
7910 {WSAENAMETOOLONG , "Name is too long"},
7911 {WSAEHOSTDOWN , "Host is down"},
7912 {WSAEHOSTUNREACH , "No route to host"},
7913 {WSAENOTEMPTY , "Buffer not empty"},
7914 {WSAEPROCLIM , "Too many processes"},
7915 {WSAEUSERS , "Too many users"},
7916 {WSAEDQUOT , "Double quote in host name"},
7917 {WSAESTALE , "Data is stale"},
7918 {WSAEREMOTE , "Remote error"},
7919
7920 {WSASYSNOTREADY , "Network subsystem is unavailable"},
7921 {WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range"},
7922 {WSANOTINITIALISED , "Winsock not initialized successfully"},
7923 {WSAEDISCON , "Graceful shutdown in progress"},
7924 #ifdef WSAENOMORE
7925 {WSAENOMORE , "No more operations allowed"},
7926 {WSAECANCELLED , "Operation cancelled"},
7927 {WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider"},
7928 {WSAEINVALIDPROVIDER , "Invalid service provider version number"},
7929 {WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider"},
7930 {WSASYSCALLFAILURE , "System call failure"},
7931 {WSASERVICE_NOT_FOUND , "Service not found"},
7932 {WSATYPE_NOT_FOUND , "Class type not found"},
7933 {WSA_E_NO_MORE , "No more resources available"},
7934 {WSA_E_CANCELLED , "Operation already cancelled"},
7935 {WSAEREFUSED , "Operation refused"},
7936 #endif
7937
7938 {WSAHOST_NOT_FOUND , "Host not found"},
7939 {WSATRY_AGAIN , "Authoritative host not found during name lookup"},
7940 {WSANO_RECOVERY , "Non-recoverable error during name lookup"},
7941 {WSANO_DATA , "Valid name, no data record of requested type"},
7942
7943 {-1, NULL}
7944 };
7945
7946 char *
7947 sys_strerror (int error_no)
7948 {
7949 int i;
7950 static char unknown_msg[40];
7951
7952 if (error_no >= 0 && error_no < sys_nerr)
7953 return sys_errlist[error_no];
7954
7955 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
7956 if (_wsa_errlist[i].errnum == error_no)
7957 return (char *)_wsa_errlist[i].msg;
7958
7959 sprintf (unknown_msg, "Unidentified error: %d", error_no);
7960 return unknown_msg;
7961 }
7962
7963
7964
7965
7966
7967 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
7968
7969 static int socket_to_fd (SOCKET s);
7970
7971 int
7972 sys_socket (int af, int type, int protocol)
7973 {
7974 SOCKET s;
7975
7976 if (winsock_lib == NULL)
7977 {
7978 errno = ENETDOWN;
7979 return -1;
7980 }
7981
7982 check_errno ();
7983
7984
7985 s = pfn_socket (af, type, protocol);
7986
7987 if (s != INVALID_SOCKET)
7988 return socket_to_fd (s);
7989
7990 set_errno ();
7991 return -1;
7992 }
7993
7994
7995 static int
7996 socket_to_fd (SOCKET s)
7997 {
7998 int fd;
7999 child_process * cp;
8000
8001
8002
8003
8004
8005
8006
8007
8008 fd = _open ("NUL:", _O_RDWR);
8009 if (fd >= 0)
8010 {
8011
8012
8013
8014
8015 {
8016
8017
8018
8019
8020
8021 if (pfn_SetHandleInformation)
8022 {
8023 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
8024 }
8025 else
8026 {
8027 HANDLE parent = GetCurrentProcess ();
8028 HANDLE new_s = INVALID_HANDLE_VALUE;
8029
8030 if (DuplicateHandle (parent,
8031 (HANDLE) s,
8032 parent,
8033 &new_s,
8034 0,
8035 FALSE,
8036 DUPLICATE_SAME_ACCESS))
8037 {
8038
8039
8040
8041
8042 unsigned long nonblocking = 0;
8043 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
8044 {
8045 pfn_closesocket (s);
8046 s = (SOCKET) new_s;
8047 }
8048 else
8049 {
8050 CloseHandle (new_s);
8051 }
8052 }
8053 }
8054 }
8055 eassert (fd < MAXDESC);
8056 fd_info[fd].hnd = (HANDLE) s;
8057
8058
8059 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
8060
8061 cp = new_child ();
8062 if (cp)
8063 {
8064 cp->fd = fd;
8065 cp->status = STATUS_READ_ACKNOWLEDGED;
8066
8067
8068 if (fd_info[ fd ].cp != NULL)
8069 {
8070 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
8071 emacs_abort ();
8072 }
8073
8074 fd_info[ fd ].cp = cp;
8075
8076
8077 winsock_inuse++;
8078 return fd;
8079 }
8080
8081
8082 _close (fd);
8083 }
8084 else
8085 pfn_closesocket (s);
8086 errno = EMFILE;
8087 return -1;
8088 }
8089
8090 int
8091 sys_bind (int s, const struct sockaddr * addr, int namelen)
8092 {
8093 if (winsock_lib == NULL)
8094 {
8095 errno = ENOTSOCK;
8096 return SOCKET_ERROR;
8097 }
8098
8099 check_errno ();
8100 if (fd_info[s].flags & FILE_SOCKET)
8101 {
8102 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
8103 if (rc == SOCKET_ERROR)
8104 set_errno ();
8105 return rc;
8106 }
8107 errno = ENOTSOCK;
8108 return SOCKET_ERROR;
8109 }
8110
8111 int
8112 sys_connect (int s, const struct sockaddr * name, int namelen)
8113 {
8114 if (winsock_lib == NULL)
8115 {
8116 errno = ENOTSOCK;
8117 return SOCKET_ERROR;
8118 }
8119
8120 check_errno ();
8121 if (fd_info[s].flags & FILE_SOCKET)
8122 {
8123 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
8124 if (rc == SOCKET_ERROR)
8125 {
8126 set_errno ();
8127
8128
8129
8130 if (errno == EWOULDBLOCK && (fd_info[s].flags & FILE_NDELAY) != 0)
8131 {
8132 errno = EINPROGRESS;
8133 fd_info[s].flags |= FILE_CONNECT;
8134 }
8135 }
8136 return rc;
8137 }
8138 errno = ENOTSOCK;
8139 return SOCKET_ERROR;
8140 }
8141
8142 u_short
8143 sys_htons (u_short hostshort)
8144 {
8145 return (winsock_lib != NULL) ?
8146 pfn_htons (hostshort) : hostshort;
8147 }
8148
8149 u_short
8150 sys_ntohs (u_short netshort)
8151 {
8152 return (winsock_lib != NULL) ?
8153 pfn_ntohs (netshort) : netshort;
8154 }
8155 u_long
8156 sys_htonl (u_long hostlong)
8157 {
8158 return (winsock_lib != NULL) ?
8159 pfn_htonl (hostlong) : hostlong;
8160 }
8161
8162 u_long
8163 sys_ntohl (u_long netlong)
8164 {
8165 return (winsock_lib != NULL) ?
8166 pfn_ntohl (netlong) : netlong;
8167 }
8168
8169 unsigned long
8170 sys_inet_addr (const char * cp)
8171 {
8172 return (winsock_lib != NULL) ?
8173 pfn_inet_addr (cp) : INADDR_NONE;
8174 }
8175
8176 int
8177 sys_gethostname (char * name, int namelen)
8178 {
8179 if (winsock_lib != NULL)
8180 {
8181 int retval;
8182
8183 check_errno ();
8184 retval = pfn_gethostname (name, namelen);
8185 if (retval == SOCKET_ERROR)
8186 set_errno ();
8187 return retval;
8188 }
8189
8190 if (namelen > MAX_COMPUTERNAME_LENGTH)
8191 return !GetComputerName (name, (DWORD *)&namelen);
8192
8193 errno = EFAULT;
8194 return SOCKET_ERROR;
8195 }
8196
8197 struct hostent *
8198 sys_gethostbyname (const char * name)
8199 {
8200 struct hostent * host;
8201 int h_err = h_errno;
8202
8203 if (winsock_lib == NULL)
8204 {
8205 h_errno = NO_RECOVERY;
8206 errno = ENETDOWN;
8207 return NULL;
8208 }
8209
8210 check_errno ();
8211 host = pfn_gethostbyname (name);
8212 if (!host)
8213 {
8214 set_errno ();
8215 h_errno = errno;
8216 }
8217 else
8218 h_errno = h_err;
8219 return host;
8220 }
8221
8222 struct servent *
8223 sys_getservbyname (const char * name, const char * proto)
8224 {
8225 struct servent * serv;
8226
8227 if (winsock_lib == NULL)
8228 {
8229 errno = ENETDOWN;
8230 return NULL;
8231 }
8232
8233 check_errno ();
8234 serv = pfn_getservbyname (name, proto);
8235 if (!serv)
8236 set_errno ();
8237 return serv;
8238 }
8239
8240 int
8241 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
8242 {
8243 if (winsock_lib == NULL)
8244 {
8245 errno = ENETDOWN;
8246 return SOCKET_ERROR;
8247 }
8248
8249 check_errno ();
8250 if (fd_info[s].flags & FILE_SOCKET)
8251 {
8252 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
8253 if (rc == SOCKET_ERROR)
8254 set_errno ();
8255 return rc;
8256 }
8257 errno = ENOTSOCK;
8258 return SOCKET_ERROR;
8259 }
8260
8261 int
8262 sys_getaddrinfo (const char *node, const char *service,
8263 const struct addrinfo *hints, struct addrinfo **res)
8264 {
8265 int rc;
8266
8267 if (winsock_lib == NULL)
8268 {
8269 errno = ENETDOWN;
8270 return SOCKET_ERROR;
8271 }
8272
8273 check_errno ();
8274 if (pfn_getaddrinfo)
8275 rc = pfn_getaddrinfo (node, service, hints, res);
8276 else
8277 {
8278 int port = 0;
8279 struct hostent *host_info;
8280 struct gai_storage {
8281 struct addrinfo addrinfo;
8282 struct sockaddr_in sockaddr_in;
8283 } *gai_storage;
8284
8285
8286 if (hints && hints->ai_flags != 0)
8287 return WSAEINVAL;
8288
8289 if (!node)
8290 return WSAHOST_NOT_FOUND;
8291
8292 if (service)
8293 {
8294 const char *protocol =
8295 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
8296 struct servent *srv = sys_getservbyname (service, protocol);
8297
8298 if (srv)
8299 port = srv->s_port;
8300 else if (*service >= '0' && *service <= '9')
8301 {
8302 char *endp;
8303
8304 port = strtoul (service, &endp, 10);
8305 if (*endp || port > 65536)
8306 return WSAHOST_NOT_FOUND;
8307 port = sys_htons ((unsigned short) port);
8308 }
8309 else
8310 return WSAHOST_NOT_FOUND;
8311 }
8312
8313 gai_storage = xzalloc (sizeof *gai_storage);
8314 gai_storage->sockaddr_in.sin_port = port;
8315 host_info = sys_gethostbyname (node);
8316 if (host_info)
8317 {
8318 memcpy (&gai_storage->sockaddr_in.sin_addr,
8319 host_info->h_addr, host_info->h_length);
8320 gai_storage->sockaddr_in.sin_family = host_info->h_addrtype;
8321 }
8322 else
8323 {
8324
8325 unsigned long numeric_addr = sys_inet_addr (node);
8326
8327 if (numeric_addr == -1)
8328 {
8329 free (gai_storage);
8330 return WSAHOST_NOT_FOUND;
8331 }
8332
8333 memcpy (&gai_storage->sockaddr_in.sin_addr, &numeric_addr,
8334 sizeof (gai_storage->sockaddr_in.sin_addr));
8335 gai_storage->sockaddr_in.sin_family = (hints) ? hints->ai_family : 0;
8336 }
8337
8338 gai_storage->addrinfo.ai_addr =
8339 (struct sockaddr *)&gai_storage->sockaddr_in;
8340 gai_storage->addrinfo.ai_addrlen = sizeof (gai_storage->sockaddr_in);
8341 gai_storage->addrinfo.ai_protocol = (hints) ? hints->ai_protocol : 0;
8342 gai_storage->addrinfo.ai_socktype = (hints) ? hints->ai_socktype : 0;
8343 gai_storage->addrinfo.ai_family = gai_storage->sockaddr_in.sin_family;
8344 gai_storage->addrinfo.ai_next = NULL;
8345
8346 *res = &gai_storage->addrinfo;
8347 rc = 0;
8348 }
8349
8350 return rc;
8351 }
8352
8353 void
8354 sys_freeaddrinfo (struct addrinfo *ai)
8355 {
8356 if (winsock_lib == NULL)
8357 {
8358 errno = ENETDOWN;
8359 return;
8360 }
8361
8362 check_errno ();
8363 if (pfn_freeaddrinfo)
8364 pfn_freeaddrinfo (ai);
8365 else
8366 {
8367 eassert (ai->ai_next == NULL);
8368 xfree (ai);
8369 }
8370 }
8371
8372 int
8373 sys_shutdown (int s, int how)
8374 {
8375 if (winsock_lib == NULL)
8376 {
8377 errno = ENETDOWN;
8378 return SOCKET_ERROR;
8379 }
8380
8381 check_errno ();
8382 if (fd_info[s].flags & FILE_SOCKET)
8383 {
8384 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
8385 if (rc == SOCKET_ERROR)
8386 set_errno ();
8387 return rc;
8388 }
8389 errno = ENOTSOCK;
8390 return SOCKET_ERROR;
8391 }
8392
8393 int
8394 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
8395 {
8396 if (winsock_lib == NULL)
8397 {
8398 errno = ENETDOWN;
8399 return SOCKET_ERROR;
8400 }
8401
8402 check_errno ();
8403 if (fd_info[s].flags & FILE_SOCKET)
8404 {
8405 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
8406 (const char *)optval, optlen);
8407 if (rc == SOCKET_ERROR)
8408 set_errno ();
8409 return rc;
8410 }
8411 errno = ENOTSOCK;
8412 return SOCKET_ERROR;
8413 }
8414
8415 int
8416 sys_listen (int s, int backlog)
8417 {
8418 if (winsock_lib == NULL)
8419 {
8420 errno = ENETDOWN;
8421 return SOCKET_ERROR;
8422 }
8423
8424 check_errno ();
8425 if (fd_info[s].flags & FILE_SOCKET)
8426 {
8427 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
8428 if (rc == SOCKET_ERROR)
8429 set_errno ();
8430 else
8431 fd_info[s].flags |= FILE_LISTEN;
8432 return rc;
8433 }
8434 errno = ENOTSOCK;
8435 return SOCKET_ERROR;
8436 }
8437
8438 int
8439 sys_getsockname (int s, struct sockaddr * name, int * namelen)
8440 {
8441 if (winsock_lib == NULL)
8442 {
8443 errno = ENETDOWN;
8444 return SOCKET_ERROR;
8445 }
8446
8447 check_errno ();
8448 if (fd_info[s].flags & FILE_SOCKET)
8449 {
8450 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
8451 if (rc == SOCKET_ERROR)
8452 set_errno ();
8453 return rc;
8454 }
8455 errno = ENOTSOCK;
8456 return SOCKET_ERROR;
8457 }
8458
8459 int
8460 sys_accept (int s, struct sockaddr * addr, int * addrlen)
8461 {
8462 if (winsock_lib == NULL)
8463 {
8464 errno = ENETDOWN;
8465 return -1;
8466 }
8467
8468 check_errno ();
8469 if (fd_info[s].flags & FILE_LISTEN)
8470 {
8471 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
8472 int fd = -1;
8473 if (t == INVALID_SOCKET)
8474 set_errno ();
8475 else
8476 fd = socket_to_fd (t);
8477
8478 if (fd >= 0)
8479 {
8480 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
8481 ResetEvent (fd_info[s].cp->char_avail);
8482 }
8483 return fd;
8484 }
8485 errno = ENOTSOCK;
8486 return -1;
8487 }
8488
8489 int
8490 sys_recvfrom (int s, char * buf, int len, int flags,
8491 struct sockaddr * from, int * fromlen)
8492 {
8493 if (winsock_lib == NULL)
8494 {
8495 errno = ENETDOWN;
8496 return SOCKET_ERROR;
8497 }
8498
8499 check_errno ();
8500 if (fd_info[s].flags & FILE_SOCKET)
8501 {
8502 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
8503 if (rc == SOCKET_ERROR)
8504 set_errno ();
8505 return rc;
8506 }
8507 errno = ENOTSOCK;
8508 return SOCKET_ERROR;
8509 }
8510
8511 int
8512 sys_sendto (int s, const char * buf, int len, int flags,
8513 const struct sockaddr * to, int tolen)
8514 {
8515 if (winsock_lib == NULL)
8516 {
8517 errno = ENETDOWN;
8518 return SOCKET_ERROR;
8519 }
8520
8521 check_errno ();
8522 if (fd_info[s].flags & FILE_SOCKET)
8523 {
8524 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
8525 if (rc == SOCKET_ERROR)
8526 set_errno ();
8527 return rc;
8528 }
8529 errno = ENOTSOCK;
8530 return SOCKET_ERROR;
8531 }
8532
8533
8534
8535 int
8536 fcntl (int s, int cmd, int options)
8537 {
8538
8539
8540
8541 if (cmd == F_DUPFD_CLOEXEC)
8542 return sys_dup (s);
8543
8544 check_errno ();
8545 if (fd_info[s].flags & FILE_SOCKET)
8546 {
8547 if (winsock_lib == NULL)
8548 {
8549 errno = ENETDOWN;
8550 return -1;
8551 }
8552
8553 if (cmd == F_SETFL && options == O_NONBLOCK)
8554 {
8555 unsigned long nblock = 1;
8556 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
8557 if (rc == SOCKET_ERROR)
8558 set_errno ();
8559
8560 fd_info[s].flags |= FILE_NDELAY;
8561 return rc;
8562 }
8563 else
8564 {
8565 errno = EINVAL;
8566 return SOCKET_ERROR;
8567 }
8568 }
8569 else if ((fd_info[s].flags & (FILE_PIPE | FILE_WRITE))
8570 == (FILE_PIPE | FILE_WRITE))
8571 {
8572
8573 if (cmd == F_SETFL && options == O_NONBLOCK)
8574 {
8575 HANDLE h = (HANDLE)_get_osfhandle (s);
8576 DWORD pipe_mode = PIPE_NOWAIT;
8577
8578 if (!SetNamedPipeHandleState (h, &pipe_mode, NULL, NULL))
8579 {
8580 DebPrint (("SetNamedPipeHandleState: %lu\n", GetLastError ()));
8581 return SOCKET_ERROR;
8582 }
8583 fd_info[s].flags |= FILE_NDELAY;
8584 return 0;
8585 }
8586 else
8587 {
8588 errno = EINVAL;
8589 return SOCKET_ERROR;
8590 }
8591 }
8592 errno = ENOTSOCK;
8593 return SOCKET_ERROR;
8594 }
8595
8596
8597
8598
8599
8600 int
8601 sys_close (int fd)
8602 {
8603 int rc = -1;
8604 bool reader_thread_exited = false;
8605
8606 if (fd < 0)
8607 {
8608 errno = EBADF;
8609 return -1;
8610 }
8611
8612 if (fd < MAXDESC && fd_info[fd].cp)
8613 {
8614 child_process * cp = fd_info[fd].cp;
8615 DWORD thrd_status = STILL_ACTIVE;
8616
8617
8618 if (cp->thrd != NULL
8619 && GetExitCodeThread (cp->thrd, &thrd_status)
8620 && thrd_status != STILL_ACTIVE)
8621 reader_thread_exited = true;
8622
8623 fd_info[fd].cp = NULL;
8624
8625 if (CHILD_ACTIVE (cp))
8626 {
8627
8628 int i;
8629 for (i = 0; i < MAXDESC; i++)
8630 {
8631 if (i == fd)
8632 continue;
8633 if (fd_info[i].cp == cp)
8634 break;
8635 }
8636 if (i == MAXDESC)
8637 {
8638 if (fd_info[fd].flags & FILE_SOCKET)
8639 {
8640 if (winsock_lib == NULL) emacs_abort ();
8641
8642 pfn_shutdown (SOCK_HANDLE (fd), 2);
8643 rc = pfn_closesocket (SOCK_HANDLE (fd));
8644
8645 winsock_inuse--;
8646 }
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658 if (cp->procinfo.hProcess == NULL)
8659 delete_child (cp);
8660 else
8661 cp->fd = -1;
8662 }
8663 }
8664 }
8665
8666
8667
8668
8669
8670 if (fd < MAXDESC)
8671 {
8672 if ((fd_info[fd].flags & FILE_DONT_CLOSE) == 0
8673
8674
8675
8676 || reader_thread_exited)
8677 {
8678 fd_info[fd].flags = 0;
8679 rc = _close (fd);
8680 }
8681 else
8682 {
8683
8684
8685
8686
8687
8688
8689
8690 rc = 0;
8691
8692
8693 fd_info[fd].flags = FILE_DONT_CLOSE;
8694 }
8695 }
8696
8697 return rc;
8698 }
8699
8700 int
8701 sys_dup (int fd)
8702 {
8703 int new_fd;
8704
8705 new_fd = _dup (fd);
8706 if (new_fd >= 0 && new_fd < MAXDESC)
8707 {
8708
8709 fd_info[new_fd] = fd_info[fd];
8710 }
8711 return new_fd;
8712 }
8713
8714 int
8715 sys_dup2 (int src, int dst)
8716 {
8717 int rc;
8718
8719 if (dst < 0 || dst >= MAXDESC)
8720 {
8721 errno = EBADF;
8722 return -1;
8723 }
8724
8725
8726
8727
8728
8729
8730
8731 if (src == dst)
8732 {
8733 if ((HANDLE)_get_osfhandle (src) == INVALID_HANDLE_VALUE)
8734 {
8735 errno = EBADF;
8736 return -1;
8737 }
8738 return dst;
8739 }
8740
8741
8742 if (fd_info[dst].flags != 0)
8743 sys_close (dst);
8744
8745 rc = _dup2 (src, dst);
8746 if (rc == 0)
8747 {
8748
8749 fd_info[dst] = fd_info[src];
8750 }
8751 return rc == 0 ? dst : rc;
8752 }
8753
8754 int
8755 pipe2 (int * phandles, int pipe2_flags)
8756 {
8757 int rc;
8758 unsigned flags;
8759 unsigned pipe_size = 0;
8760
8761 eassert (pipe2_flags == (O_BINARY | O_CLOEXEC));
8762
8763
8764 if (w32_pipe_buffer_size > 0 && w32_pipe_buffer_size < UINT_MAX)
8765 pipe_size = w32_pipe_buffer_size;
8766
8767
8768
8769
8770
8771 rc = _pipe (phandles, pipe_size, _O_NOINHERIT | _O_BINARY);
8772
8773 if (rc == 0)
8774 {
8775
8776
8777 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
8778 {
8779 _close (phandles[0]);
8780 _close (phandles[1]);
8781
8782
8783
8784
8785 phandles[0] = phandles[1] = -1;
8786 errno = EMFILE;
8787 rc = -1;
8788 }
8789 else
8790 {
8791 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
8792 fd_info[phandles[0]].flags = flags;
8793
8794 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
8795 fd_info[phandles[1]].flags = flags;
8796 }
8797 }
8798
8799 return rc;
8800 }
8801
8802
8803
8804
8805 int
8806 _sys_read_ahead (int fd)
8807 {
8808 child_process * cp;
8809 int rc = 0;
8810
8811 if (fd < 0 || fd >= MAXDESC)
8812 return STATUS_READ_ERROR;
8813
8814 cp = fd_info[fd].cp;
8815
8816 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8817 return STATUS_READ_ERROR;
8818
8819 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SERIAL | FILE_SOCKET)) == 0
8820 || (fd_info[fd].flags & FILE_READ) == 0)
8821 {
8822 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
8823 emacs_abort ();
8824 }
8825
8826 if ((fd_info[fd].flags & FILE_CONNECT) != 0)
8827 DebPrint (("_sys_read_ahead: read requested from fd %d, which waits for async connect!\n", fd));
8828 cp->status = STATUS_READ_IN_PROGRESS;
8829
8830 if (fd_info[fd].flags & FILE_PIPE)
8831 {
8832 rc = _read (fd, &cp->chr, sizeof (char));
8833
8834
8835
8836
8837
8838
8839
8840
8841
8842 if (rc > 0)
8843 {
8844 int wait = w32_pipe_read_delay;
8845
8846 if (wait > 0)
8847 Sleep (wait);
8848 else if (wait < 0)
8849 while (++wait <= 0)
8850
8851
8852 Sleep (0);
8853 }
8854 }
8855 else if (fd_info[fd].flags & FILE_SERIAL)
8856 {
8857 HANDLE hnd = fd_info[fd].hnd;
8858 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
8859 COMMTIMEOUTS ct;
8860
8861
8862 if (!GetCommTimeouts (hnd, &ct))
8863 {
8864 cp->status = STATUS_READ_ERROR;
8865 return STATUS_READ_ERROR;
8866 }
8867 ct.ReadIntervalTimeout = 0;
8868 ct.ReadTotalTimeoutMultiplier = 0;
8869 ct.ReadTotalTimeoutConstant = 0;
8870 if (!SetCommTimeouts (hnd, &ct))
8871 {
8872 cp->status = STATUS_READ_ERROR;
8873 return STATUS_READ_ERROR;
8874 }
8875
8876 if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
8877 {
8878 if (GetLastError () != ERROR_IO_PENDING)
8879 {
8880 cp->status = STATUS_READ_ERROR;
8881 return STATUS_READ_ERROR;
8882 }
8883 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
8884 {
8885 cp->status = STATUS_READ_ERROR;
8886 return STATUS_READ_ERROR;
8887 }
8888 }
8889 }
8890 else if (fd_info[fd].flags & FILE_SOCKET)
8891 {
8892 unsigned long nblock = 0;
8893
8894 if (fd_info[fd].flags & FILE_NDELAY)
8895 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8896
8897 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
8898
8899 if (fd_info[fd].flags & FILE_NDELAY)
8900 {
8901 nblock = 1;
8902 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
8903 }
8904 }
8905
8906 if (rc == sizeof (char))
8907 cp->status = STATUS_READ_SUCCEEDED;
8908 else
8909 cp->status = STATUS_READ_FAILED;
8910
8911 return cp->status;
8912 }
8913
8914 int
8915 _sys_wait_accept (int fd)
8916 {
8917 HANDLE hEv;
8918 child_process * cp;
8919 int rc;
8920
8921 if (fd < 0 || fd >= MAXDESC)
8922 return STATUS_READ_ERROR;
8923
8924 cp = fd_info[fd].cp;
8925
8926 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8927 return STATUS_READ_ERROR;
8928
8929 cp->status = STATUS_READ_FAILED;
8930
8931 hEv = pfn_WSACreateEvent ();
8932 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
8933 if (rc != SOCKET_ERROR)
8934 {
8935 do {
8936 rc = WaitForSingleObject (hEv, 500);
8937 Sleep (5);
8938 } while (rc == WAIT_TIMEOUT
8939 && cp->status != STATUS_READ_ERROR
8940 && cp->char_avail);
8941 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8942 if (rc == WAIT_OBJECT_0)
8943 cp->status = STATUS_READ_SUCCEEDED;
8944 }
8945 pfn_WSACloseEvent (hEv);
8946
8947 return cp->status;
8948 }
8949
8950 int
8951 _sys_wait_connect (int fd)
8952 {
8953 HANDLE hEv;
8954 child_process * cp;
8955 int rc;
8956
8957 if (fd < 0 || fd >= MAXDESC)
8958 return STATUS_READ_ERROR;
8959
8960 cp = fd_info[fd].cp;
8961 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
8962 return STATUS_READ_ERROR;
8963
8964 cp->status = STATUS_READ_FAILED;
8965
8966 hEv = pfn_WSACreateEvent ();
8967 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_CONNECT);
8968 if (rc != SOCKET_ERROR)
8969 {
8970 do {
8971 rc = WaitForSingleObject (hEv, 500);
8972 Sleep (5);
8973 } while (rc == WAIT_TIMEOUT
8974 && cp->status != STATUS_READ_ERROR
8975 && cp->char_avail);
8976 if (rc == WAIT_OBJECT_0)
8977 {
8978
8979
8980
8981 WSANETWORKEVENTS events;
8982
8983 pfn_WSAEnumNetworkEvents (SOCK_HANDLE (fd), hEv, &events);
8984 if ((events.lNetworkEvents & FD_CONNECT) != 0
8985 && events.iErrorCode[FD_CONNECT_BIT])
8986 {
8987 cp->status = STATUS_CONNECT_FAILED;
8988 cp->errcode = events.iErrorCode[FD_CONNECT_BIT];
8989 }
8990 else
8991 {
8992 cp->status = STATUS_READ_SUCCEEDED;
8993 cp->errcode = 0;
8994 }
8995 }
8996 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
8997 }
8998 else
8999 pfn_WSACloseEvent (hEv);
9000
9001 return cp->status;
9002 }
9003
9004 int
9005 sys_read (int fd, char * buffer, unsigned int count)
9006 {
9007 int nchars;
9008 int to_read;
9009 DWORD waiting;
9010 char * orig_buffer = buffer;
9011
9012 if (fd < 0)
9013 {
9014 errno = EBADF;
9015 return -1;
9016 }
9017
9018 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
9019 {
9020 child_process *cp = fd_info[fd].cp;
9021
9022 if ((fd_info[fd].flags & FILE_READ) == 0)
9023 {
9024 errno = EBADF;
9025 return -1;
9026 }
9027
9028 nchars = 0;
9029
9030
9031 if (fd_info[fd].flags & FILE_LAST_CR)
9032 {
9033 if (fd_info[fd].flags & FILE_BINARY) emacs_abort ();
9034 *buffer++ = 0x0d;
9035 count--;
9036 nchars++;
9037 fd_info[fd].flags &= ~FILE_LAST_CR;
9038 }
9039
9040
9041
9042
9043
9044
9045 if (cp)
9046 {
9047 int current_status = cp->status;
9048
9049 switch (current_status)
9050 {
9051 case STATUS_READ_FAILED:
9052 case STATUS_READ_ERROR:
9053
9054 if (nchars <= 0)
9055 fd_info[fd].flags |= FILE_AT_EOF;
9056 return nchars;
9057
9058 case STATUS_READ_READY:
9059 case STATUS_READ_IN_PROGRESS:
9060 #if 0
9061
9062
9063
9064
9065
9066
9067
9068 DebPrint (("sys_read called when read is in progress %d\n",
9069 current_status));
9070 #endif
9071 errno = EWOULDBLOCK;
9072 return -1;
9073
9074 case STATUS_READ_SUCCEEDED:
9075
9076 *buffer++ = cp->chr;
9077 count--;
9078 nchars++;
9079 cp->status = STATUS_READ_ACKNOWLEDGED;
9080 ResetEvent (cp->char_avail);
9081
9082 case STATUS_READ_ACKNOWLEDGED:
9083 case STATUS_CONNECT_FAILED:
9084 break;
9085
9086 default:
9087 DebPrint (("sys_read: bad status %d\n", current_status));
9088 errno = EBADF;
9089 return -1;
9090 }
9091
9092 if (fd_info[fd].flags & FILE_PIPE)
9093 {
9094 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
9095 to_read = min (waiting, (DWORD) count);
9096
9097 if (to_read > 0)
9098 nchars += _read (fd, buffer, to_read);
9099 }
9100 else if (fd_info[fd].flags & FILE_SERIAL)
9101 {
9102 HANDLE hnd = fd_info[fd].hnd;
9103 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
9104 int rc = 0;
9105 COMMTIMEOUTS ct;
9106
9107 if (count > 0)
9108 {
9109
9110 if (!GetCommTimeouts (hnd, &ct))
9111 {
9112 errno = EIO;
9113 return -1;
9114 }
9115 ct.ReadIntervalTimeout = MAXDWORD;
9116 ct.ReadTotalTimeoutMultiplier = 0;
9117 ct.ReadTotalTimeoutConstant = 0;
9118 if (!SetCommTimeouts (hnd, &ct))
9119 {
9120 errno = EIO;
9121 return -1;
9122 }
9123
9124 if (!ResetEvent (ovl->hEvent))
9125 {
9126 errno = EIO;
9127 return -1;
9128 }
9129 if (!ReadFile (hnd, buffer, count, (DWORD*) &rc, ovl))
9130 {
9131 if (GetLastError () != ERROR_IO_PENDING)
9132 {
9133 errno = EIO;
9134 return -1;
9135 }
9136 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
9137 {
9138 errno = EIO;
9139 return -1;
9140 }
9141 }
9142 nchars += rc;
9143 }
9144 }
9145 else
9146 {
9147 if (winsock_lib == NULL) emacs_abort ();
9148
9149
9150
9151
9152
9153
9154
9155
9156
9157
9158
9159
9160
9161
9162
9163 if (current_status == STATUS_CONNECT_FAILED
9164 && (fd_info[fd].flags & FILE_CONNECT) != 0
9165 && cp->errcode != 0)
9166 {
9167 pfn_WSASetLastError (cp->errcode);
9168 set_errno ();
9169 return -1;
9170 }
9171
9172 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
9173 if (waiting == 0 && nchars == 0)
9174 {
9175 errno = EWOULDBLOCK;
9176 return -1;
9177 }
9178
9179 if (waiting)
9180 {
9181
9182 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
9183 if (res == SOCKET_ERROR)
9184 {
9185 set_errno ();
9186 DebPrint (("sys_read.recv failed with error %d on socket %ld\n",
9187 errno, SOCK_HANDLE (fd)));
9188 return -1;
9189 }
9190 nchars += res;
9191 }
9192 }
9193 }
9194 else
9195 {
9196 int nread = _read (fd, buffer, count);
9197 if (nread >= 0)
9198 nchars += nread;
9199 else if (nchars == 0)
9200 nchars = nread;
9201 }
9202
9203 if (nchars <= 0)
9204 fd_info[fd].flags |= FILE_AT_EOF;
9205
9206 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
9207 {
9208 nchars = crlf_to_lf (nchars, orig_buffer);
9209
9210
9211
9212
9213 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
9214 {
9215 fd_info[fd].flags |= FILE_LAST_CR;
9216 nchars--;
9217 }
9218 }
9219 }
9220 else
9221 nchars = _read (fd, buffer, count);
9222
9223 return nchars;
9224 }
9225
9226
9227 extern HANDLE interrupt_handle;
9228
9229 int
9230 sys_write (int fd, const void * buffer, unsigned int count)
9231 {
9232 int nchars;
9233 USE_SAFE_ALLOCA;
9234
9235 if (fd < 0)
9236 {
9237 errno = EBADF;
9238 return -1;
9239 }
9240
9241 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
9242 {
9243 if ((fd_info[fd].flags & FILE_WRITE) == 0)
9244 {
9245 errno = EBADF;
9246 return -1;
9247 }
9248
9249
9250 if ((fd_info[fd].flags & FILE_BINARY) == 0)
9251 {
9252 char * tmpbuf;
9253 const unsigned char * src = buffer;
9254 unsigned char * dst;
9255 int nbytes = count;
9256
9257 SAFE_NALLOCA (tmpbuf, 2, count);
9258 dst = (unsigned char *)tmpbuf;
9259
9260 while (1)
9261 {
9262 unsigned char *next;
9263
9264 next = _memccpy (dst, src, '\n', nbytes);
9265 if (next)
9266 {
9267
9268 int copied = next - dst;
9269 nbytes -= copied;
9270 src += copied;
9271
9272 next[-1] = '\r';
9273 next[0] = '\n';
9274 dst = next + 1;
9275 count++;
9276 }
9277 else
9278
9279 break;
9280 }
9281 buffer = tmpbuf;
9282 }
9283 }
9284
9285 if (fd < MAXDESC && fd_info[fd].flags & FILE_SERIAL)
9286 {
9287 HANDLE hnd = (HANDLE) _get_osfhandle (fd);
9288 OVERLAPPED *ovl = &fd_info[fd].cp->ovl_write;
9289 HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent };
9290 DWORD active = 0;
9291
9292
9293
9294
9295 if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl))
9296 {
9297 if (GetLastError () != ERROR_IO_PENDING)
9298 {
9299 errno = EIO;
9300 nchars = -1;
9301 }
9302 else
9303 {
9304
9305
9306 if (detect_input_pending ())
9307 active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE,
9308 INFINITE, QS_ALLINPUT);
9309 else
9310 active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE);
9311 switch (active)
9312 {
9313 case WAIT_OBJECT_0:
9314
9315
9316
9317 PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR);
9318 CancelIo (hnd);
9319 errno = EIO;
9320 nchars = -1;
9321 break;
9322 case WAIT_OBJECT_0 + 1:
9323 if (!GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE))
9324 {
9325 errno = EIO;
9326 nchars = -1;
9327 }
9328 break;
9329 }
9330 }
9331 }
9332 }
9333 else if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
9334 {
9335 unsigned long nblock = 0;
9336 if (winsock_lib == NULL) emacs_abort ();
9337
9338 child_process *cp = fd_info[fd].cp;
9339
9340
9341
9342
9343 if (cp != NULL && (fd_info[fd].flags & FILE_CONNECT) != 0)
9344 {
9345
9346
9347 if (cp->status != STATUS_CONNECT_FAILED)
9348 {
9349 errno = EWOULDBLOCK;
9350 return -1;
9351 }
9352
9353
9354 else if (cp->errcode != 0)
9355 {
9356 pfn_WSASetLastError (cp->errcode);
9357 set_errno ();
9358 return -1;
9359 }
9360 }
9361
9362
9363
9364 if (fd_info[fd].flags & FILE_NDELAY)
9365 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
9366
9367 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
9368
9369 if (nchars == SOCKET_ERROR)
9370 {
9371 set_errno ();
9372 DebPrint (("sys_write.send failed with error %d on socket %ld\n",
9373 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
9374 }
9375
9376
9377
9378 if (fd_info[fd].flags & FILE_NDELAY)
9379 {
9380 nblock = 1;
9381 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
9382 }
9383 }
9384 else
9385 {
9386
9387
9388
9389
9390
9391
9392 const unsigned char *p = buffer;
9393 const bool is_pipe = (fd < MAXDESC
9394 && ((fd_info[fd].flags & (FILE_PIPE | FILE_NDELAY))
9395 == (FILE_PIPE | FILE_NDELAY)));
9396
9397
9398
9399
9400
9401 DWORD pipe_buffer_size;
9402 if (is_pipe)
9403 {
9404 if (!GetNamedPipeInfo ((HANDLE)_get_osfhandle (fd),
9405 NULL, &pipe_buffer_size, NULL, NULL))
9406 {
9407 DebPrint (("GetNamedPipeInfo: error %u\n", GetLastError ()));
9408 pipe_buffer_size = 4096;
9409 }
9410 }
9411 const unsigned chunk = is_pipe ? pipe_buffer_size : 30 * 1024 * 1024;
9412
9413 nchars = 0;
9414 errno = 0;
9415 while (count > 0)
9416 {
9417 unsigned this_chunk = count < chunk ? count : chunk;
9418 int n = _write (fd, p, this_chunk);
9419
9420 if (n > 0)
9421 nchars += n;
9422 if (n < 0)
9423 {
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435 if (errno == ENOSPC && is_pipe)
9436 errno = EAGAIN;
9437 if (nchars == 0)
9438 nchars = -1;
9439 break;
9440 }
9441 else if (n < this_chunk)
9442 break;
9443 count -= n;
9444 p += n;
9445 }
9446 }
9447
9448 SAFE_FREE ();
9449 return nchars;
9450 }
9451
9452
9453
9454
9455
9456
9457 static Lisp_Object
9458 network_interface_get_info (Lisp_Object ifname)
9459 {
9460 ULONG ainfo_len = sizeof (IP_ADAPTER_INFO);
9461 IP_ADAPTER_INFO *adapter, *ainfo = xmalloc (ainfo_len);
9462 DWORD retval = get_adapters_info (ainfo, &ainfo_len);
9463 Lisp_Object res = Qnil;
9464
9465 if (retval == ERROR_BUFFER_OVERFLOW)
9466 {
9467 ainfo = xrealloc (ainfo, ainfo_len);
9468 retval = get_adapters_info (ainfo, &ainfo_len);
9469 }
9470
9471 if (retval == ERROR_SUCCESS)
9472 {
9473 int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
9474 int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
9475 int if_num;
9476 struct sockaddr_in sa;
9477
9478
9479
9480
9481
9482 if (!winsock_lib && !init_winsock (1))
9483 goto done;
9484
9485 for (adapter = ainfo; adapter; adapter = adapter->Next)
9486 {
9487 char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
9488 u_long ip_addr;
9489
9490
9491
9492 static const char *ifmt[] = {
9493 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9494 "lo", "ifx%d"
9495 };
9496 enum {
9497 NONE = -1,
9498 ETHERNET = 0,
9499 TOKENRING = 1,
9500 FDDI = 2,
9501 PPP = 3,
9502 SLIP = 4,
9503 WLAN = 5,
9504 LOOPBACK = 6,
9505 OTHER_IF = 7
9506 } ifmt_idx;
9507
9508 switch (adapter->Type)
9509 {
9510 case MIB_IF_TYPE_ETHERNET:
9511
9512
9513
9514 if (strstr (adapter->Description, "Wireless "))
9515 {
9516 ifmt_idx = WLAN;
9517 if_num = wlan_count++;
9518 }
9519 else
9520 {
9521 ifmt_idx = ETHERNET;
9522 if_num = eth_count++;
9523 }
9524 break;
9525 case MIB_IF_TYPE_TOKENRING:
9526 ifmt_idx = TOKENRING;
9527 if_num = tr_count++;
9528 break;
9529 case MIB_IF_TYPE_FDDI:
9530 ifmt_idx = FDDI;
9531 if_num = fddi_count++;
9532 break;
9533 case MIB_IF_TYPE_PPP:
9534 ifmt_idx = PPP;
9535 if_num = ppp_count++;
9536 break;
9537 case MIB_IF_TYPE_SLIP:
9538 ifmt_idx = SLIP;
9539 if_num = sl_count++;
9540 break;
9541 case IF_TYPE_IEEE80211:
9542 ifmt_idx = WLAN;
9543 if_num = wlan_count++;
9544 break;
9545 case MIB_IF_TYPE_LOOPBACK:
9546 if (lo_count < 0)
9547 {
9548 ifmt_idx = LOOPBACK;
9549 if_num = lo_count++;
9550 }
9551 else
9552 ifmt_idx = NONE;
9553 break;
9554 default:
9555 ifmt_idx = OTHER_IF;
9556 if_num = ifx_count++;
9557 break;
9558 }
9559 if (ifmt_idx == NONE)
9560 continue;
9561 sprintf (namebuf, ifmt[ifmt_idx], if_num);
9562
9563 sa.sin_family = AF_INET;
9564 ip_addr = sys_inet_addr (adapter->IpAddressList.IpAddress.String);
9565 if (ip_addr == INADDR_NONE)
9566 {
9567
9568 continue;
9569 }
9570 sa.sin_addr.s_addr = ip_addr;
9571 sa.sin_port = 0;
9572 if (NILP (ifname))
9573 res = Fcons (Fcons (build_string (namebuf),
9574 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9575 sizeof (struct sockaddr))),
9576 res);
9577 else if (strcmp (namebuf, SSDATA (ifname)) == 0)
9578 {
9579 Lisp_Object hwaddr = Fmake_vector (make_fixnum (6), Qnil);
9580 register struct Lisp_Vector *p = XVECTOR (hwaddr);
9581 Lisp_Object flags = Qnil;
9582 int n;
9583 u_long net_mask;
9584
9585
9586
9587 flags = Fcons (intern ("up"), flags);
9588 if (ifmt_idx == ETHERNET || ifmt_idx == WLAN)
9589 {
9590 flags = Fcons (intern ("broadcast"), flags);
9591 flags = Fcons (intern ("multicast"), flags);
9592 }
9593 flags = Fcons (intern ("running"), flags);
9594 if (ifmt_idx == PPP)
9595 {
9596 flags = Fcons (intern ("pointopoint"), flags);
9597 flags = Fcons (intern ("noarp"), flags);
9598 }
9599 if (adapter->HaveWins)
9600 flags = Fcons (intern ("WINS"), flags);
9601 if (adapter->DhcpEnabled)
9602 flags = Fcons (intern ("dynamic"), flags);
9603
9604 res = Fcons (flags, res);
9605
9606
9607 for (n = 0; n < adapter->AddressLength; n++)
9608 p->contents[n] = make_fixnum ((int) adapter->Address[n]);
9609
9610
9611
9612 res = Fcons (Fcons (make_fixnum (1), hwaddr), res);
9613
9614
9615 sa.sin_family = AF_INET;
9616 net_mask = sys_inet_addr (adapter->IpAddressList.IpMask.String);
9617 if (net_mask != INADDR_NONE)
9618 {
9619 sa.sin_addr.s_addr = net_mask;
9620 sa.sin_port = 0;
9621 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9622 sizeof (struct sockaddr)),
9623 res);
9624 }
9625 else
9626 res = Fcons (Qnil, res);
9627
9628 sa.sin_family = AF_INET;
9629 if (ip_addr != INADDR_NONE)
9630 {
9631
9632
9633
9634 u_long bcast_addr = (ip_addr & net_mask) | ~net_mask;
9635
9636 sa.sin_addr.s_addr = bcast_addr;
9637 sa.sin_port = 0;
9638 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9639 sizeof (struct sockaddr)),
9640 res);
9641
9642
9643 sa.sin_addr.s_addr = ip_addr;
9644 sa.sin_port = 0;
9645 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9646 sizeof (struct sockaddr)),
9647 res);
9648 }
9649 else
9650 res = Fcons (Qnil, Fcons (Qnil, res));
9651 }
9652 }
9653
9654
9655 if (!lo_count)
9656 {
9657 sa.sin_family = AF_INET;
9658 sa.sin_port = 0;
9659 if (NILP (ifname))
9660 {
9661 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9662 res = Fcons (Fcons (build_string ("lo"),
9663 conv_sockaddr_to_lisp ((struct sockaddr*) &sa,
9664 sizeof (struct sockaddr))),
9665 res);
9666 }
9667 else if (strcmp (SSDATA (ifname), "lo") == 0)
9668 {
9669 res = Fcons (Fcons (intern ("running"),
9670 Fcons (intern ("loopback"),
9671 Fcons (intern ("up"), Qnil))), Qnil);
9672
9673
9674 res = Fcons (Fcons (make_fixnum (772),
9675 Fmake_vector (make_fixnum (6),
9676 make_fixnum (0))),
9677 res);
9678 sa.sin_addr.s_addr = sys_inet_addr ("255.0.0.0");
9679 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9680 sizeof (struct sockaddr)),
9681 res);
9682 sa.sin_addr.s_addr = sys_inet_addr ("0.0.0.0");
9683 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9684 sizeof (struct sockaddr)),
9685 res);
9686 sa.sin_addr.s_addr = sys_inet_addr ("127.0.0.1");
9687 res = Fcons (conv_sockaddr_to_lisp ((struct sockaddr *) &sa,
9688 sizeof (struct sockaddr)),
9689 res);
9690 }
9691
9692 }
9693 }
9694
9695 done:
9696 xfree (ainfo);
9697 return res;
9698 }
9699
9700 static bool
9701 address_prefix_match (int family, struct sockaddr *address,
9702 struct sockaddr *prefix_address, ULONG prefix_len)
9703 {
9704 UINT8 *address_data;
9705 UINT8 *prefix_address_data;
9706 int i;
9707
9708 if (family == AF_INET6)
9709 {
9710 address_data = (UINT8 *) &(((struct sockaddr_in6 *) address)->sin6_addr);
9711 prefix_address_data =
9712 (UINT8 *) &(((struct sockaddr_in6 *) prefix_address)->sin6_addr);
9713 }
9714 else
9715 {
9716 address_data = (UINT8 *) &(((struct sockaddr_in *) address)->sin_addr);
9717 prefix_address_data =
9718 (UINT8 *) &(((struct sockaddr_in *) prefix_address)->sin_addr);
9719 }
9720
9721 for (i = 0; i < prefix_len >> 3; i++)
9722 {
9723 if (address_data[i] != prefix_address_data[i])
9724 return false;
9725 }
9726
9727 if (prefix_len % 8)
9728 return (prefix_address_data[i] ==
9729 (address_data[i] & (0xff << (8 - prefix_len % 8))));
9730
9731 return true;
9732 }
9733
9734 Lisp_Object
9735 network_interface_list (bool full, unsigned short match)
9736 {
9737 ULONG ainfo_len = sizeof (IP_ADAPTER_ADDRESSES);
9738 ULONG family = match;
9739 IP_ADAPTER_ADDRESSES *adapter, *ainfo = xmalloc (ainfo_len);
9740 DWORD retval = get_adapters_addresses (family, ainfo, &ainfo_len);
9741 Lisp_Object res = Qnil;
9742
9743 if (retval == ERROR_BUFFER_OVERFLOW)
9744 {
9745 ainfo = xrealloc (ainfo, ainfo_len);
9746 retval = get_adapters_addresses (family, ainfo, &ainfo_len);
9747 }
9748
9749 if (retval != ERROR_SUCCESS)
9750 {
9751 xfree (ainfo);
9752 return res;
9753 }
9754
9755
9756
9757
9758
9759 if (!winsock_lib && !init_winsock (1))
9760 return res;
9761
9762 int eth_count = 0, tr_count = 0, fddi_count = 0, ppp_count = 0;
9763 int sl_count = 0, wlan_count = 0, lo_count = 0, ifx_count = 0;
9764 int tnl_count = 0;
9765 int if_num;
9766 char namebuf[MAX_ADAPTER_NAME_LENGTH + 4];
9767 static const char *ifmt[] = {
9768 "eth%d", "tr%d", "fddi%d", "ppp%d", "sl%d", "wlan%d",
9769 "lo%d", "ifx%d", "tunnel%d"
9770 };
9771 enum {
9772 NONE = -1,
9773 ETHERNET = 0,
9774 TOKENRING = 1,
9775 FDDI = 2,
9776 PPP = 3,
9777 SLIP = 4,
9778 WLAN = 5,
9779 LOOPBACK = 6,
9780 OTHER_IF = 7,
9781 TUNNEL = 8
9782 } ifmt_idx;
9783
9784 for (adapter = ainfo; adapter; adapter = adapter->Next)
9785 {
9786
9787
9788
9789
9790
9791 switch (adapter->IfType)
9792 {
9793 case IF_TYPE_ETHERNET_CSMACD:
9794
9795
9796
9797 {
9798 char description[MAX_UTF8_PATH];
9799 if (filename_from_utf16 (adapter->Description, description) == 0
9800 && strstr (description, "Wireless "))
9801 {
9802 ifmt_idx = WLAN;
9803 if_num = wlan_count++;
9804 }
9805 else
9806 {
9807 ifmt_idx = ETHERNET;
9808 if_num = eth_count++;
9809 }
9810 }
9811 break;
9812 case IF_TYPE_ISO88025_TOKENRING:
9813 ifmt_idx = TOKENRING;
9814 if_num = tr_count++;
9815 break;
9816 case IF_TYPE_FDDI:
9817 ifmt_idx = FDDI;
9818 if_num = fddi_count++;
9819 break;
9820 case IF_TYPE_PPP:
9821 ifmt_idx = PPP;
9822 if_num = ppp_count++;
9823 break;
9824 case IF_TYPE_SLIP:
9825 ifmt_idx = SLIP;
9826 if_num = sl_count++;
9827 break;
9828 case IF_TYPE_IEEE80211:
9829 ifmt_idx = WLAN;
9830 if_num = wlan_count++;
9831 break;
9832 case IF_TYPE_SOFTWARE_LOOPBACK:
9833 ifmt_idx = LOOPBACK;
9834 if_num = lo_count++;
9835 break;
9836 case IF_TYPE_TUNNEL:
9837 ifmt_idx = TUNNEL;
9838 if_num = tnl_count++;
9839 break;
9840 default:
9841 ifmt_idx = OTHER_IF;
9842 if_num = ifx_count++;
9843 break;
9844 }
9845 sprintf (namebuf, ifmt[ifmt_idx], if_num);
9846
9847 IP_ADAPTER_UNICAST_ADDRESS *address;
9848 for (address = adapter->FirstUnicastAddress; address; address = address->Next)
9849 {
9850 int len;
9851 int addr_len;
9852 uint32_t *maskp;
9853 uint32_t *addrp;
9854 Lisp_Object elt = Qnil;
9855 struct sockaddr *ifa_addr = address->Address.lpSockaddr;
9856
9857 if (ifa_addr == NULL)
9858 continue;
9859 if (match && ifa_addr->sa_family != match)
9860 continue;
9861
9862 struct sockaddr_in ipv4;
9863 #ifdef AF_INET6
9864 struct sockaddr_in6 ipv6;
9865 #endif
9866 struct sockaddr *sin;
9867
9868 if (ifa_addr->sa_family == AF_INET)
9869 {
9870 ipv4.sin_family = AF_INET;
9871 ipv4.sin_port = 0;
9872 DECLARE_POINTER_ALIAS (sin_in, struct sockaddr_in, ifa_addr);
9873 addrp = (uint32_t *)&sin_in->sin_addr;
9874 maskp = (uint32_t *)&ipv4.sin_addr;
9875 sin = (struct sockaddr *)&ipv4;
9876 len = sizeof (struct sockaddr_in);
9877 addr_len = 1;
9878 }
9879 #ifdef AF_INET6
9880 else if (ifa_addr->sa_family == AF_INET6)
9881 {
9882 ipv6.sin6_family = AF_INET6;
9883 ipv6.sin6_port = 0;
9884 DECLARE_POINTER_ALIAS (sin_in6, struct sockaddr_in6, ifa_addr);
9885 addrp = (uint32_t *)&sin_in6->sin6_addr;
9886 maskp = (uint32_t *)&ipv6.sin6_addr;
9887 sin = (struct sockaddr *)&ipv6;
9888 len = sizeof (struct sockaddr_in6);
9889 addr_len = 4;
9890 }
9891 #endif
9892 else
9893 continue;
9894
9895 Lisp_Object addr = conv_sockaddr_to_lisp (ifa_addr, len);
9896
9897 if (full)
9898 {
9899
9900
9901
9902 int i;
9903 ULONG numbits;
9904 if (w32_major_version >= 6)
9905 {
9906 #if _WIN32_WINNT >= 0x0600
9907 numbits = address->OnLinkPrefixLength;
9908 #else
9909
9910
9911 numbits = *(UINT8 *) (&address->LeaseLifetime + 1);
9912 #endif
9913 }
9914 else
9915 {
9916 IP_ADAPTER_PREFIX *prefix = adapter->FirstPrefix;
9917 numbits = 0;
9918 for ( ; prefix; prefix = prefix->Next)
9919 {
9920
9921 if ((prefix->Address.lpSockaddr->sa_family
9922 == ifa_addr->sa_family)
9923 && (prefix->PrefixLength > numbits)
9924 && address_prefix_match (ifa_addr->sa_family,
9925 ifa_addr,
9926 prefix->Address.lpSockaddr,
9927 prefix->PrefixLength))
9928 numbits = prefix->PrefixLength;
9929 }
9930 if (!numbits)
9931 numbits = (ifa_addr->sa_family == AF_INET6) ? 128 : 32;
9932 }
9933 for (i = 0; i < addr_len; i++)
9934 {
9935 if (numbits >= 32)
9936 {
9937 maskp[i] = -1U;
9938 numbits -= 32;
9939 }
9940 else if (numbits)
9941 {
9942 maskp[i] = sys_htonl (-1U << (32 - numbits));
9943 numbits = 0;
9944 }
9945 else
9946 {
9947 maskp[i] = 0;
9948 }
9949 }
9950 elt = Fcons (conv_sockaddr_to_lisp (sin, len), elt);
9951 uint32_t mask;
9952 for (i = 0; i < addr_len; i++)
9953 {
9954 mask = maskp[i];
9955 maskp[i] = (addrp[i] & mask) | ~mask;
9956
9957 }
9958 elt = Fcons (conv_sockaddr_to_lisp (sin, len), elt);
9959 elt = Fcons (addr, elt);
9960 }
9961 else
9962 {
9963 elt = addr;
9964 }
9965 res = Fcons (Fcons (build_string (namebuf), elt), res);
9966 }
9967 }
9968 xfree (ainfo);
9969 return res;
9970 }
9971
9972 Lisp_Object
9973 network_interface_info (Lisp_Object ifname)
9974 {
9975 CHECK_STRING (ifname);
9976 return network_interface_get_info (ifname);
9977 }
9978
9979
9980
9981 Lisp_Object
9982 w32_read_registry (HKEY rootkey, Lisp_Object lkey, Lisp_Object lname)
9983 {
9984 HKEY hkey = NULL;
9985 LONG status;
9986 DWORD vsize, vtype;
9987 LPBYTE pvalue;
9988 Lisp_Object val, retval;
9989 const char *key, *value_name = NULL;
9990
9991
9992 wchar_t key_w[255+1];
9993 wchar_t value_w[16*1024+1];
9994 bool use_unicode = is_windows_9x () == 0;
9995
9996 if (use_unicode)
9997 {
9998 Lisp_Object encoded_key, encoded_vname;
9999
10000
10001 encoded_key = code_convert_string_norecord (lkey, Qutf_16le, 1);
10002 memcpy (key_w, SSDATA (encoded_key), SBYTES (encoded_key));
10003
10004 key_w [SBYTES (encoded_key)/2] = L'\0';
10005 encoded_vname = code_convert_string_norecord (lname, Qutf_16le, 1);
10006 memcpy (value_w, SSDATA (encoded_vname), SBYTES (encoded_vname));
10007 value_w[SBYTES (encoded_vname)/2] = L'\0';
10008
10009
10010 for (int i = 0; i < SBYTES (encoded_key)/2; i++)
10011 {
10012 if (key_w[i] == L'/')
10013 key_w[i] = L'\\';
10014 }
10015 if ((status = reg_open_key_ex_w (rootkey, key_w, 0,
10016 KEY_READ, &hkey)) == ERROR_NOT_SUPPORTED
10017 || (status = reg_query_value_ex_w (hkey, value_w, NULL, NULL, NULL,
10018 &vsize)) == ERROR_NOT_SUPPORTED
10019 || status != ERROR_SUCCESS)
10020 {
10021 if (hkey)
10022 RegCloseKey (hkey);
10023 if (status != ERROR_NOT_SUPPORTED)
10024 return Qnil;
10025 use_unicode = 0;
10026 }
10027 }
10028 if (!use_unicode)
10029 {
10030
10031 Lisp_Object local_lkey = Fcopy_sequence (lkey);
10032
10033
10034
10035
10036
10037 for (int i = 0; i < SBYTES (local_lkey); i++)
10038 {
10039 if (SSDATA (local_lkey)[i] == '/')
10040 SSDATA (local_lkey)[i] = '\\';
10041 }
10042
10043 key = SSDATA (ENCODE_SYSTEM (local_lkey));
10044 value_name = SSDATA (ENCODE_SYSTEM (lname));
10045
10046 if ((status = RegOpenKeyEx (rootkey, key, 0,
10047 KEY_READ, &hkey)) != ERROR_SUCCESS
10048 || (status = RegQueryValueEx (hkey, value_name, NULL,
10049 NULL, NULL, &vsize)) != ERROR_SUCCESS)
10050 {
10051 if (hkey)
10052 RegCloseKey (hkey);
10053 return Qnil;
10054 }
10055 }
10056
10057 pvalue = xzalloc (vsize);
10058 if (use_unicode)
10059 status = reg_query_value_ex_w (hkey, value_w, NULL, &vtype, pvalue, &vsize);
10060 else
10061 status = RegQueryValueEx (hkey, value_name, NULL, &vtype, pvalue, &vsize);
10062 if (status != ERROR_SUCCESS)
10063 {
10064 xfree (pvalue);
10065 RegCloseKey (hkey);
10066 return Qnil;
10067 }
10068
10069 switch (vtype)
10070 {
10071 case REG_NONE:
10072 retval = Qt;
10073 break;
10074 case REG_DWORD:
10075 retval = INT_TO_INTEGER (*((DWORD *)pvalue));
10076 break;
10077 case REG_QWORD:
10078 retval = INT_TO_INTEGER (*((long long *)pvalue));
10079 break;
10080 case REG_BINARY:
10081 {
10082 int i;
10083 unsigned char *dbuf = (unsigned char *)pvalue;
10084
10085 val = make_uninit_vector (vsize);
10086 for (i = 0; i < vsize; i++)
10087 ASET (val, i, make_fixnum (dbuf[i]));
10088
10089 retval = val;
10090 break;
10091 }
10092 case REG_SZ:
10093 if (use_unicode)
10094 {
10095
10096
10097 if (pvalue[vsize - 1] == '\0')
10098 vsize -= 2;
10099 AUTO_STRING_WITH_LEN (sval, (char *)pvalue, vsize);
10100 retval = from_unicode (sval);
10101 }
10102 else
10103 {
10104
10105
10106 if (pvalue[vsize - 1] == '\0')
10107 vsize--;
10108 retval = DECODE_SYSTEM (make_unibyte_string (pvalue, vsize));
10109 }
10110 break;
10111 case REG_EXPAND_SZ:
10112 if (use_unicode)
10113 {
10114 wchar_t expanded_w[32*1024];
10115 DWORD dsize = sizeof (expanded_w) / 2;
10116 DWORD produced = expand_environment_strings_w ((wchar_t *)pvalue,
10117 expanded_w,
10118 dsize);
10119 if (produced > 0 && produced < dsize)
10120 {
10121 AUTO_STRING_WITH_LEN (sval, (char *)expanded_w,
10122 produced * 2 - 2);
10123 retval = from_unicode (sval);
10124 }
10125 else
10126 {
10127 if (pvalue[vsize - 1] == '\0')
10128 vsize -= 2;
10129 AUTO_STRING_WITH_LEN (sval, (char *)pvalue, vsize);
10130 retval = from_unicode (sval);
10131 }
10132 }
10133 else
10134 {
10135 char expanded[32*1024];
10136 DWORD produced = ExpandEnvironmentStrings ((char *)pvalue,
10137 expanded,
10138 sizeof (expanded));
10139 if (produced > 0 && produced < sizeof (expanded))
10140 retval = make_unibyte_string (expanded, produced - 1);
10141 else
10142 {
10143 if (pvalue[vsize - 1] == '\0')
10144 vsize--;
10145 retval = make_unibyte_string (pvalue, vsize);
10146 }
10147
10148 retval = DECODE_SYSTEM (retval);
10149 }
10150 break;
10151 case REG_MULTI_SZ:
10152 if (use_unicode)
10153 {
10154 wchar_t *wp = (wchar_t *)pvalue;
10155
10156 val = Qnil;
10157 do {
10158 size_t wslen = wcslen (wp);
10159 AUTO_STRING_WITH_LEN (sval, (char *)wp, wslen * 2);
10160 val = Fcons (from_unicode (sval), val);
10161 wp += wslen + 1;
10162 } while (*wp);
10163 }
10164 else
10165 {
10166 char *p = (char *)pvalue;
10167
10168 val = Qnil;
10169 do {
10170 size_t slen = strlen (p);
10171
10172 val = Fcons (DECODE_SYSTEM (make_unibyte_string (p, slen)), val);
10173 p += slen + 1;
10174 } while (*p);
10175 }
10176
10177 retval = Fnreverse (val);
10178 break;
10179 default:
10180 error ("unsupported registry data type: %d", (int)vtype);
10181 }
10182
10183 xfree (pvalue);
10184 RegCloseKey (hkey);
10185 return retval;
10186 }
10187
10188
10189
10190
10191
10192
10193
10194
10195 struct tm *
10196 sys_localtime (const time_t *t)
10197 {
10198 tzset ();
10199 return localtime (t);
10200 }
10201
10202
10203
10204
10205 clock_t
10206 sys_clock (void)
10207 {
10208 if (get_process_times_fn)
10209 {
10210 FILETIME create, exit, kernel, user;
10211 HANDLE proc = GetCurrentProcess ();
10212 if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
10213 {
10214 LARGE_INTEGER user_int, kernel_int, total;
10215 user_int.LowPart = user.dwLowDateTime;
10216 user_int.HighPart = user.dwHighDateTime;
10217 kernel_int.LowPart = kernel.dwLowDateTime;
10218 kernel_int.HighPart = kernel.dwHighDateTime;
10219 total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
10220
10221
10222
10223 return total.QuadPart / (10000000 / CLOCKS_PER_SEC);
10224 }
10225 }
10226 return clock ();
10227 }
10228
10229
10230
10231
10232
10233
10234
10235
10236
10237
10238
10239 HMODULE
10240 w32_delayed_load (Lisp_Object library_id)
10241 {
10242 HMODULE dll_handle = NULL;
10243
10244 CHECK_SYMBOL (library_id);
10245
10246 if (CONSP (Vdynamic_library_alist)
10247 && NILP (Fassq (library_id, Vlibrary_cache)))
10248 {
10249 Lisp_Object found = Qnil;
10250 Lisp_Object dlls = Fassq (library_id, Vdynamic_library_alist);
10251
10252 if (CONSP (dlls))
10253 for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
10254 {
10255 Lisp_Object dll = XCAR (dlls);
10256 char name[MAX_UTF8_PATH];
10257 DWORD res = -1;
10258
10259 CHECK_STRING (dll);
10260 dll = ENCODE_FILE (dll);
10261 if (w32_unicode_filenames)
10262 {
10263 wchar_t name_w[MAX_PATH];
10264
10265 filename_to_utf16 (SSDATA (dll), name_w);
10266 dll_handle = LoadLibraryW (name_w);
10267 if (dll_handle)
10268 {
10269 res = GetModuleFileNameW (dll_handle, name_w,
10270 sizeof (name_w));
10271 if (res > 0)
10272 filename_from_utf16 (name_w, name);
10273 }
10274 }
10275 else
10276 {
10277 char name_a[MAX_PATH];
10278
10279 filename_to_ansi (SSDATA (dll), name_a);
10280 dll_handle = LoadLibraryA (name_a);
10281 if (dll_handle)
10282 {
10283 res = GetModuleFileNameA (dll_handle, name_a,
10284 sizeof (name_a));
10285 if (res > 0)
10286 filename_from_ansi (name_a, name);
10287 }
10288 }
10289 if (dll_handle)
10290 {
10291 ptrdiff_t len = strlen (name);
10292 found = Fcons (dll,
10293 (res > 0)
10294
10295 ? make_specified_string (name, -1, len, 1)
10296 : Qnil);
10297
10298
10299
10300
10301
10302
10303 DisableThreadLibraryCalls (dll_handle);
10304 break;
10305 }
10306 }
10307
10308 Fput (library_id, QCloaded_from, found);
10309 }
10310
10311 return dll_handle;
10312 }
10313
10314
10315 void
10316 check_windows_init_file (void)
10317 {
10318
10319
10320
10321
10322 if (!noninteractive && !inhibit_window_system
10323
10324
10325 && NILP (Vpurify_flag))
10326 {
10327 Lisp_Object init_file;
10328 int fd;
10329
10330
10331
10332
10333
10334
10335
10336 init_file = build_string ("term/w32-win");
10337 fd =
10338 openp (Vload_path, init_file, Fget_load_suffixes (), NULL, Qnil, 0, 0,
10339 NULL);
10340 if (fd < 0)
10341 {
10342 Lisp_Object load_path_print = Fprin1_to_string (Vload_path,
10343 Qnil, Qnil);
10344 char *init_file_name = SSDATA (init_file);
10345 char *load_path = SSDATA (load_path_print);
10346 char *buffer = alloca (1024
10347 + strlen (init_file_name)
10348 + strlen (load_path));
10349 char *msg = buffer;
10350 int needed;
10351
10352 sprintf (buffer,
10353 "The Emacs Windows initialization file \"%s.el\" "
10354 "could not be found in your Emacs installation. "
10355 "Emacs checked the following directories for this file:\n"
10356 "\n%s\n\n"
10357 "When Emacs cannot find this file, it usually means that it "
10358 "was not installed properly, or its distribution file was "
10359 "not unpacked properly.\nSee the README.W32 file in the "
10360 "top-level Emacs directory for more information.",
10361 init_file_name, load_path);
10362 needed = pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags,
10363 buffer, -1, NULL, 0);
10364 if (needed > 0)
10365 {
10366 wchar_t *msg_w = alloca ((needed + 1) * sizeof (wchar_t));
10367
10368 pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, buffer,
10369 -1, msg_w, needed);
10370 needed = pWideCharToMultiByte (CP_ACP, 0, msg_w, -1,
10371 NULL, 0, NULL, NULL);
10372 if (needed > 0)
10373 {
10374 char *msg_a = alloca (needed + 1);
10375
10376 pWideCharToMultiByte (CP_ACP, 0, msg_w, -1, msg_a, needed,
10377 NULL, NULL);
10378 msg = msg_a;
10379 }
10380 }
10381 MessageBox (NULL,
10382 msg,
10383 "Emacs Abort Dialog",
10384 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
10385
10386 abort ();
10387 }
10388 else
10389 {
10390 _close (fd);
10391 }
10392 }
10393 }
10394
10395 void
10396 term_ntproc (int ignored)
10397 {
10398 (void)ignored;
10399
10400 term_timers ();
10401
10402
10403 term_winsock ();
10404
10405 term_w32select ();
10406
10407 #if HAVE_NATIVE_IMAGE_API
10408 w32_gdiplus_shutdown ();
10409 #endif
10410 }
10411
10412 void
10413 init_ntproc (int dumping)
10414 {
10415 sigset_t initial_mask = 0;
10416
10417
10418
10419
10420
10421
10422
10423
10424
10425
10426 winsock_lib = NULL;
10427
10428 if (getenv ("PRELOAD_WINSOCK") != NULL)
10429 init_winsock (TRUE);
10430
10431
10432
10433 {
10434 HANDLE parent;
10435 HANDLE stdin_save = INVALID_HANDLE_VALUE;
10436 HANDLE stdout_save = INVALID_HANDLE_VALUE;
10437 HANDLE stderr_save = INVALID_HANDLE_VALUE;
10438
10439 parent = GetCurrentProcess ();
10440
10441
10442
10443 DuplicateHandle (parent,
10444 GetStdHandle (STD_INPUT_HANDLE),
10445 parent,
10446 &stdin_save,
10447 0,
10448 FALSE,
10449 DUPLICATE_SAME_ACCESS);
10450
10451 DuplicateHandle (parent,
10452 GetStdHandle (STD_OUTPUT_HANDLE),
10453 parent,
10454 &stdout_save,
10455 0,
10456 FALSE,
10457 DUPLICATE_SAME_ACCESS);
10458
10459 DuplicateHandle (parent,
10460 GetStdHandle (STD_ERROR_HANDLE),
10461 parent,
10462 &stderr_save,
10463 0,
10464 FALSE,
10465 DUPLICATE_SAME_ACCESS);
10466
10467 fclose (stdin);
10468 fclose (stdout);
10469 fclose (stderr);
10470
10471 if (stdin_save != INVALID_HANDLE_VALUE)
10472 _open_osfhandle ((intptr_t) stdin_save, O_TEXT);
10473 else
10474 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
10475 _fdopen (0, "r");
10476
10477 if (stdout_save != INVALID_HANDLE_VALUE)
10478 _open_osfhandle ((intptr_t) stdout_save, O_TEXT);
10479 else
10480 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
10481 _fdopen (1, "w");
10482
10483 if (stderr_save != INVALID_HANDLE_VALUE)
10484 _open_osfhandle ((intptr_t) stderr_save, O_TEXT);
10485 else
10486 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
10487 _fdopen (2, "w");
10488 }
10489
10490
10491
10492 if (!dumping)
10493 {
10494
10495 sigprocmask (SIG_SETMASK, &initial_mask, NULL);
10496 signal (SIGABRT, term_ntproc);
10497 }
10498 init_timers ();
10499
10500
10501 {
10502
10503 char drive[] = "A:\\";
10504
10505
10506 while (*drive <= 'Z')
10507 {
10508
10509 fixed_drives[DRIVE_INDEX (*drive)] =
10510 (GetDriveType (drive) == DRIVE_FIXED);
10511
10512 (*drive)++;
10513 }
10514
10515
10516 volume_cache = NULL;
10517 }
10518 }
10519
10520
10521
10522
10523
10524
10525 extern DWORD dwMainThreadId;
10526
10527 static BOOL WINAPI
10528 shutdown_handler (DWORD type)
10529 {
10530
10531 if (type == CTRL_CLOSE_EVENT
10532 || type == CTRL_LOGOFF_EVENT
10533 || type == CTRL_SHUTDOWN_EVENT)
10534 {
10535 if (GetCurrentThreadId () == dwMainThreadId)
10536 {
10537
10538
10539
10540
10541
10542 if (noninteractive)
10543 clear_message_stack ();
10544
10545 shut_down_emacs (0, Qnil);
10546 }
10547 else
10548 {
10549
10550
10551
10552
10553
10554
10555
10556
10557 Vquit_flag = Qkill_emacs;
10558 Vinhibit_quit = Qnil;
10559 }
10560 }
10561
10562
10563 return FALSE;
10564 }
10565
10566
10567
10568 HANDLE
10569 maybe_load_unicows_dll (void)
10570 {
10571 if (os_subtype == OS_SUBTYPE_9X)
10572 {
10573 HANDLE ret = LoadLibrary ("Unicows.dll");
10574 if (ret)
10575 {
10576
10577
10578
10579
10580
10581
10582 pMultiByteToWideChar = (MultiByteToWideChar_Proc)
10583 get_proc_addr (ret, "MultiByteToWideChar");
10584 pWideCharToMultiByte = (WideCharToMultiByte_Proc)
10585 get_proc_addr (ret, "WideCharToMultiByte");
10586 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
10587 return ret;
10588 }
10589 else
10590 {
10591 int button;
10592
10593 button = MessageBox (NULL,
10594 "Emacs cannot load the UNICOWS.DLL library.\n"
10595 "This library is essential for using Emacs\n"
10596 "on this system. You need to install it.\n\n"
10597 "Emacs will exit when you click OK.",
10598 "Emacs cannot load UNICOWS.DLL",
10599 MB_ICONERROR | MB_TASKMODAL
10600 | MB_SETFOREGROUND | MB_OK);
10601 switch (button)
10602 {
10603 case IDOK:
10604 default:
10605 exit (1);
10606 }
10607 }
10608 }
10609 else
10610 {
10611
10612
10613
10614 pMultiByteToWideChar = MultiByteToWideChar;
10615 pWideCharToMultiByte = WideCharToMultiByte;
10616
10617 if (w32_major_version < 5)
10618 multiByteToWideCharFlags = 0;
10619 else
10620 multiByteToWideCharFlags = MB_ERR_INVALID_CHARS;
10621 return LoadLibrary ("Gdi32.dll");
10622 }
10623 }
10624
10625
10626
10627
10628
10629
10630 const char *
10631 w32_relocate (const char *epath_dir)
10632 {
10633 if (strncmp (epath_dir, "%emacs_dir%/", 12) == 0)
10634 {
10635 static char relocated_dir[MAX_PATH];
10636
10637
10638
10639
10640
10641 if (GetModuleFileNameA (NULL, relocated_dir, MAX_PATH))
10642 {
10643 char *p = _mbsrchr (relocated_dir, '\\');
10644
10645 if (p)
10646 {
10647 *p = '\0';
10648 if ((p = _mbsrchr (relocated_dir, '\\')) != NULL)
10649 {
10650 strcpy (p, epath_dir + 11);
10651 epath_dir = relocated_dir;
10652 }
10653 }
10654 }
10655 }
10656 return epath_dir;
10657 }
10658
10659
10660
10661
10662
10663
10664
10665 char *
10666 w32_my_exename (void)
10667 {
10668 static char exename[MAX_PATH];
10669 if (!GetModuleFileNameA (NULL, exename, MAX_PATH))
10670 return NULL;
10671
10672
10673
10674 if (get_volume_info (exename, NULL)
10675 && (volume_info.flags & FILE_SUPPORTS_REPARSE_POINTS) != 0)
10676 {
10677
10678 char exename_utf8[MAX_UTF8_PATH];
10679 filename_from_ansi (exename, exename_utf8);
10680
10681
10682 char *tgt = chase_symlinks (exename_utf8);
10683 if (tgt != exename_utf8)
10684 filename_to_ansi (tgt, exename);
10685 }
10686
10687 return exename;
10688 }
10689
10690
10691
10692 char *
10693 realpath (const char *file_name, char *resolved_name)
10694 {
10695 char *tgt = chase_symlinks (file_name);
10696 char target[MAX_UTF8_PATH];
10697
10698 if (tgt == file_name)
10699 {
10700
10701
10702
10703 if (w32_unicode_filenames)
10704 {
10705 wchar_t file_w[MAX_PATH], tgt_w[MAX_PATH];
10706
10707 filename_to_utf16 (file_name, file_w);
10708 if (GetFullPathNameW (file_w, MAX_PATH, tgt_w, NULL) == 0)
10709 return NULL;
10710 filename_from_utf16 (tgt_w, target);
10711 }
10712 else
10713 {
10714 char file_a[MAX_PATH], tgt_a[MAX_PATH];
10715
10716 filename_to_ansi (file_name, file_a);
10717 if (GetFullPathNameA (file_a, MAX_PATH, tgt_a, NULL) == 0)
10718 return NULL;
10719 filename_from_ansi (tgt_a, target);
10720 }
10721 tgt = target;
10722 }
10723
10724 if (resolved_name)
10725 return strcpy (resolved_name, tgt);
10726 return xstrdup (tgt);
10727 }
10728
10729 static void
10730 get_console_font_size (HANDLE hscreen, int *font_width, int *font_height)
10731 {
10732 static GetCurrentConsoleFont_Proc s_pfn_Get_Current_Console_Font = NULL;
10733 static GetConsoleFontSize_Proc s_pfn_Get_Console_Font_Size = NULL;
10734
10735
10736 *font_width = 8;
10737 *font_height = 12;
10738
10739 if (!is_windows_9x ())
10740 {
10741 if (g_b_init_get_console_font_size == 0)
10742 {
10743 HMODULE hm_kernel32 = LoadLibrary ("Kernel32.dll");
10744 if (hm_kernel32)
10745 {
10746 s_pfn_Get_Current_Console_Font = (GetCurrentConsoleFont_Proc)
10747 get_proc_addr (hm_kernel32, "GetCurrentConsoleFont");
10748 s_pfn_Get_Console_Font_Size = (GetConsoleFontSize_Proc)
10749 get_proc_addr (hm_kernel32, "GetConsoleFontSize");
10750 }
10751 g_b_init_get_console_font_size = 1;
10752 }
10753 }
10754 if (s_pfn_Get_Current_Console_Font && s_pfn_Get_Console_Font_Size)
10755 {
10756 CONSOLE_FONT_INFO font_info;
10757
10758 if (s_pfn_Get_Current_Console_Font (hscreen, FALSE, &font_info))
10759 {
10760 COORD font_size = s_pfn_Get_Console_Font_Size (hscreen,
10761 font_info.nFont);
10762 if (font_size.X > 0)
10763 *font_width = font_size.X;
10764 if (font_size.Y > 0)
10765 *font_height = font_size.Y;
10766 }
10767 }
10768 }
10769
10770
10771
10772
10773
10774
10775
10776 int
10777 w32_reexec_emacs (char *cmd_line, const char *wdir)
10778 {
10779 STARTUPINFO si;
10780 BOOL status;
10781 PROCESS_INFORMATION proc_info;
10782 DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS;
10783
10784 GetStartupInfo (&si);
10785 if (inhibit_window_system)
10786 {
10787 HANDLE screen_handle;
10788 CONSOLE_SCREEN_BUFFER_INFO screen_info;
10789
10790 screen_handle = GetStdHandle (STD_OUTPUT_HANDLE);
10791 if (screen_handle != INVALID_HANDLE_VALUE
10792 && GetConsoleScreenBufferInfo (screen_handle, &screen_info))
10793 {
10794 int font_width, font_height;
10795
10796
10797
10798 si.dwXCountChars = screen_info.dwSize.X;
10799 si.dwYCountChars = screen_info.dwSize.Y;
10800 get_console_font_size (screen_handle, &font_width, &font_height);
10801 si.dwXSize =
10802 (screen_info.srWindow.Right - screen_info.srWindow.Left + 1)
10803 * font_width;
10804 si.dwYSize =
10805 (screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1)
10806 * font_height;
10807 si.dwFlags |= STARTF_USESIZE | STARTF_USECOUNTCHARS;
10808 }
10809
10810
10811
10812
10813
10814
10815
10816 dwCreationFlags = CREATE_NEW_CONSOLE;
10817 }
10818
10819
10820
10821 chdir (wdir);
10822
10823 status = CreateProcess (NULL,
10824 cmd_line,
10825 NULL,
10826 NULL,
10827 FALSE,
10828 dwCreationFlags,
10829 NULL,
10830 wdir,
10831 &si,
10832 &proc_info);
10833 if (status)
10834 {
10835 CloseHandle (proc_info.hThread);
10836 CloseHandle (proc_info.hProcess);
10837 exit (0);
10838 }
10839 errno = ENOEXEC;
10840 return -1;
10841 }
10842
10843
10844
10845
10846
10847
10848 void
10849 globals_of_w32 (void)
10850 {
10851 HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
10852
10853 get_process_times_fn = (GetProcessTimes_Proc)
10854 get_proc_addr (kernel32, "GetProcessTimes");
10855
10856 DEFSYM (QCloaded_from, ":loaded-from");
10857
10858 g_b_init_is_windows_9x = 0;
10859 g_b_init_open_process_token = 0;
10860 g_b_init_get_token_information = 0;
10861 g_b_init_lookup_account_sid = 0;
10862 g_b_init_get_sid_sub_authority = 0;
10863 g_b_init_get_sid_sub_authority_count = 0;
10864 g_b_init_get_security_info = 0;
10865 g_b_init_get_file_security_w = 0;
10866 g_b_init_get_file_security_a = 0;
10867 g_b_init_get_security_descriptor_owner = 0;
10868 g_b_init_get_security_descriptor_group = 0;
10869 g_b_init_is_valid_sid = 0;
10870 g_b_init_create_toolhelp32_snapshot = 0;
10871 g_b_init_process32_first = 0;
10872 g_b_init_process32_next = 0;
10873 g_b_init_open_thread_token = 0;
10874 g_b_init_impersonate_self = 0;
10875 g_b_init_revert_to_self = 0;
10876 g_b_init_get_process_memory_info = 0;
10877 g_b_init_get_process_working_set_size = 0;
10878 g_b_init_global_memory_status = 0;
10879 g_b_init_global_memory_status_ex = 0;
10880 g_b_init_equal_sid = 0;
10881 g_b_init_copy_sid = 0;
10882 g_b_init_get_length_sid = 0;
10883 g_b_init_get_native_system_info = 0;
10884 g_b_init_get_system_times = 0;
10885 g_b_init_create_symbolic_link_w = 0;
10886 g_b_init_create_symbolic_link_a = 0;
10887 g_b_init_get_security_descriptor_dacl = 0;
10888 g_b_init_convert_sd_to_sddl = 0;
10889 g_b_init_convert_sddl_to_sd = 0;
10890 g_b_init_is_valid_security_descriptor = 0;
10891 g_b_init_set_file_security_w = 0;
10892 g_b_init_set_file_security_a = 0;
10893 g_b_init_set_named_security_info_w = 0;
10894 g_b_init_set_named_security_info_a = 0;
10895 g_b_init_get_adapters_info = 0;
10896 g_b_init_get_adapters_addresses = 0;
10897 g_b_init_reg_open_key_ex_w = 0;
10898 g_b_init_reg_query_value_ex_w = 0;
10899 g_b_init_expand_environment_strings_w = 0;
10900 g_b_init_compare_string_w = 0;
10901 g_b_init_debug_break_process = 0;
10902 g_b_init_get_user_default_ui_language = 0;
10903 g_b_init_get_console_font_size = 0;
10904 num_of_processors = 0;
10905
10906
10907
10908
10909 SetConsoleCtrlHandler (shutdown_handler, TRUE);
10910
10911
10912 strcpy (dflt_group_name, "None");
10913
10914
10915 w32_stat_get_owner_group = 0;
10916
10917
10918
10919
10920 if (is_windows_9x ())
10921 w32_unicode_filenames = 0;
10922 else
10923 w32_unicode_filenames = 1;
10924
10925 #ifdef HAVE_MODULES
10926 dynlib_reset_last_error ();
10927 #endif
10928
10929 w32_crypto_hprov = (HCRYPTPROV)0;
10930
10931
10932
10933 Vlibrary_cache = Qnil;
10934 }
10935
10936
10937 int
10938 serial_open (Lisp_Object port_obj)
10939 {
10940 char *port = SSDATA (port_obj);
10941 HANDLE hnd;
10942 child_process *cp;
10943 int fd = -1;
10944
10945 hnd = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, 0,
10946 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
10947 if (hnd == INVALID_HANDLE_VALUE)
10948 error ("Could not open %s", port);
10949 fd = (int) _open_osfhandle ((intptr_t) hnd, 0);
10950 if (fd == -1)
10951 error ("Could not open %s", port);
10952
10953 cp = new_child ();
10954 if (!cp)
10955 error ("Could not create child process");
10956 cp->fd = fd;
10957 cp->status = STATUS_READ_ACKNOWLEDGED;
10958 fd_info[ fd ].hnd = hnd;
10959 fd_info[ fd ].flags |=
10960 FILE_READ | FILE_WRITE | FILE_BINARY | FILE_SERIAL;
10961 if (fd_info[ fd ].cp != NULL)
10962 {
10963 error ("fd_info[fd = %d] is already in use", fd);
10964 }
10965 fd_info[ fd ].cp = cp;
10966 cp->ovl_read.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
10967 if (cp->ovl_read.hEvent == NULL)
10968 error ("Could not create read event");
10969 cp->ovl_write.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
10970 if (cp->ovl_write.hEvent == NULL)
10971 error ("Could not create write event");
10972
10973 return fd;
10974 }
10975
10976
10977 void
10978 serial_configure (struct Lisp_Process *p, Lisp_Object contact)
10979 {
10980 Lisp_Object childp2 = Qnil;
10981 Lisp_Object tem = Qnil;
10982 HANDLE hnd;
10983 DCB dcb;
10984 COMMTIMEOUTS ct;
10985 char summary[4] = "???";
10986
10987 if ((fd_info[ p->outfd ].flags & FILE_SERIAL) == 0)
10988 error ("Not a serial process");
10989 hnd = fd_info[ p->outfd ].hnd;
10990
10991 childp2 = Fcopy_sequence (p->childp);
10992
10993
10994 if (!GetCommTimeouts (hnd, &ct))
10995 error ("GetCommTimeouts() failed");
10996 ct.ReadIntervalTimeout = 0;
10997 ct.ReadTotalTimeoutMultiplier = 0;
10998 ct.ReadTotalTimeoutConstant = 0;
10999 ct.WriteTotalTimeoutMultiplier = 0;
11000 ct.WriteTotalTimeoutConstant = 0;
11001 if (!SetCommTimeouts (hnd, &ct))
11002 error ("SetCommTimeouts() failed");
11003
11004 memset (&dcb, 0, sizeof (dcb));
11005 dcb.DCBlength = sizeof (DCB);
11006 if (!GetCommState (hnd, &dcb))
11007 error ("GetCommState() failed");
11008 dcb.fBinary = TRUE;
11009 dcb.fNull = FALSE;
11010 dcb.fAbortOnError = FALSE;
11011
11012 dcb.ErrorChar = 0;
11013 dcb.EofChar = 0;
11014 dcb.EvtChar = 0;
11015
11016
11017 if (!NILP (plist_member (contact, QCspeed)))
11018 tem = plist_get (contact, QCspeed);
11019 else
11020 tem = plist_get (p->childp, QCspeed);
11021 CHECK_FIXNUM (tem);
11022 dcb.BaudRate = XFIXNUM (tem);
11023 childp2 = plist_put (childp2, QCspeed, tem);
11024
11025
11026 if (!NILP (plist_member (contact, QCbytesize)))
11027 tem = plist_get (contact, QCbytesize);
11028 else
11029 tem = plist_get (p->childp, QCbytesize);
11030 if (NILP (tem))
11031 tem = make_fixnum (8);
11032 CHECK_FIXNUM (tem);
11033 if (XFIXNUM (tem) != 7 && XFIXNUM (tem) != 8)
11034 error (":bytesize must be nil (8), 7, or 8");
11035 dcb.ByteSize = XFIXNUM (tem);
11036 summary[0] = XFIXNUM (tem) + '0';
11037 childp2 = plist_put (childp2, QCbytesize, tem);
11038
11039
11040 if (!NILP (plist_member (contact, QCparity)))
11041 tem = plist_get (contact, QCparity);
11042 else
11043 tem = plist_get (p->childp, QCparity);
11044 if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
11045 error (":parity must be nil (no parity), `even', or `odd'");
11046 dcb.fParity = FALSE;
11047 dcb.Parity = NOPARITY;
11048 dcb.fErrorChar = FALSE;
11049 if (NILP (tem))
11050 {
11051 summary[1] = 'N';
11052 }
11053 else if (EQ (tem, Qeven))
11054 {
11055 summary[1] = 'E';
11056 dcb.fParity = TRUE;
11057 dcb.Parity = EVENPARITY;
11058 dcb.fErrorChar = TRUE;
11059 }
11060 else if (EQ (tem, Qodd))
11061 {
11062 summary[1] = 'O';
11063 dcb.fParity = TRUE;
11064 dcb.Parity = ODDPARITY;
11065 dcb.fErrorChar = TRUE;
11066 }
11067 childp2 = plist_put (childp2, QCparity, tem);
11068
11069
11070 if (!NILP (plist_member (contact, QCstopbits)))
11071 tem = plist_get (contact, QCstopbits);
11072 else
11073 tem = plist_get (p->childp, QCstopbits);
11074 if (NILP (tem))
11075 tem = make_fixnum (1);
11076 CHECK_FIXNUM (tem);
11077 if (XFIXNUM (tem) != 1 && XFIXNUM (tem) != 2)
11078 error (":stopbits must be nil (1 stopbit), 1, or 2");
11079 summary[2] = XFIXNUM (tem) + '0';
11080 if (XFIXNUM (tem) == 1)
11081 dcb.StopBits = ONESTOPBIT;
11082 else if (XFIXNUM (tem) == 2)
11083 dcb.StopBits = TWOSTOPBITS;
11084 childp2 = plist_put (childp2, QCstopbits, tem);
11085
11086
11087 if (!NILP (plist_member (contact, QCflowcontrol)))
11088 tem = plist_get (contact, QCflowcontrol);
11089 else
11090 tem = plist_get (p->childp, QCflowcontrol);
11091 if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
11092 error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
11093 dcb.fOutxCtsFlow = FALSE;
11094 dcb.fOutxDsrFlow = FALSE;
11095 dcb.fDtrControl = DTR_CONTROL_DISABLE;
11096 dcb.fDsrSensitivity = FALSE;
11097 dcb.fTXContinueOnXoff = FALSE;
11098 dcb.fOutX = FALSE;
11099 dcb.fInX = FALSE;
11100 dcb.fRtsControl = RTS_CONTROL_DISABLE;
11101 dcb.XonChar = 17;
11102 dcb.XoffChar = 19;
11103 if (NILP (tem))
11104 {
11105
11106 }
11107 else if (EQ (tem, Qhw))
11108 {
11109 dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
11110 dcb.fOutxCtsFlow = TRUE;
11111 }
11112 else if (EQ (tem, Qsw))
11113 {
11114 dcb.fOutX = TRUE;
11115 dcb.fInX = TRUE;
11116 }
11117 childp2 = plist_put (childp2, QCflowcontrol, tem);
11118
11119
11120 if (!SetCommState (hnd, &dcb))
11121 error ("SetCommState() failed");
11122
11123 childp2 = plist_put (childp2, QCsummary, build_string (summary));
11124 pset_childp (p, childp2);
11125 }
11126
11127
11128 void
11129 register_aux_fd (int infd)
11130 {
11131 child_process *cp;
11132
11133 cp = new_child ();
11134 if (!cp)
11135 error ("Could not create child process");
11136 cp->fd = infd;
11137 cp->status = STATUS_READ_ACKNOWLEDGED;
11138
11139 if (fd_info[ infd ].cp != NULL)
11140 {
11141 error ("fd_info[fd = %d] is already in use", infd);
11142 }
11143 fd_info[ infd ].cp = cp;
11144 fd_info[ infd ].hnd = (HANDLE) _get_osfhandle (infd);
11145 fd_info[ infd ].flags |= FILE_DONT_CLOSE;
11146 }
11147
11148 #ifdef HAVE_GNUTLS
11149
11150 ssize_t
11151 emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
11152 {
11153 int n, err;
11154 struct Lisp_Process *process = (struct Lisp_Process *)p;
11155 int fd = process->infd;
11156
11157 n = sys_read (fd, (char*)buf, sz);
11158
11159 if (n >= 0)
11160 return n;
11161
11162 err = errno;
11163
11164
11165 if (err == EWOULDBLOCK)
11166 err = EAGAIN;
11167
11168 emacs_gnutls_transport_set_errno (process->gnutls_state, err);
11169
11170 return -1;
11171 }
11172
11173 ssize_t
11174 emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
11175 {
11176 struct Lisp_Process *process = (struct Lisp_Process *)p;
11177 int fd = process->outfd;
11178 ssize_t n = sys_write (fd, buf, sz);
11179
11180
11181 if (n >= 0)
11182 return n;
11183
11184
11185
11186 emacs_gnutls_transport_set_errno (process->gnutls_state,
11187 errno == EWOULDBLOCK ? EAGAIN : errno);
11188
11189 return -1;
11190 }
11191 #endif
11192
11193