1997-01-20 00:38:22 +00:00
|
|
|
|
/* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
|
2008-07-01 03:04:08 +00:00
|
|
|
|
Copyright (C) 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
|
2009-01-08 03:15:17 +00:00
|
|
|
|
2007, 2008, 2009 Free Software Foundation, Inc.
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1996-01-15 09:18:04 +00:00
|
|
|
|
This file is part of GNU Emacs.
|
|
|
|
|
|
2008-05-14 07:50:26 +00:00
|
|
|
|
GNU Emacs is free software: you can redistribute it and/or modify
|
1996-01-15 09:18:04 +00:00
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2008-05-14 07:50:26 +00:00
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
(at your option) any later version.
|
1996-01-15 09:18:04 +00:00
|
|
|
|
|
|
|
|
|
GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2008-05-14 07:50:26 +00:00
|
|
|
|
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
2008-05-14 07:50:26 +00:00
|
|
|
|
/*
|
1994-11-01 10:27:02 +00:00
|
|
|
|
Geoff Voelker (voelker@cs.washington.edu) 7-29-94
|
|
|
|
|
*/
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#include <stddef.h> /* for offsetof */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
2009-07-04 10:43:10 +00:00
|
|
|
|
#include <float.h> /* for DBL_EPSILON */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
#include <io.h>
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#include <errno.h>
|
1994-11-01 10:27:02 +00:00
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <ctype.h>
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#include <signal.h>
|
1998-06-05 16:08:32 +00:00
|
|
|
|
#include <sys/file.h>
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#include <sys/time.h>
|
1998-04-23 23:41:12 +00:00
|
|
|
|
#include <sys/utime.h>
|
2007-02-23 18:40:41 +00:00
|
|
|
|
#include <mbstring.h> /* for _mbspbrk */
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
#include <math.h>
|
2009-10-19 04:27:09 +00:00
|
|
|
|
#include <setjmp.h>
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* must include CRT headers *before* config.h */
|
2002-01-01 19:15:26 +00:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#undef access
|
|
|
|
|
#undef chdir
|
|
|
|
|
#undef chmod
|
|
|
|
|
#undef creat
|
|
|
|
|
#undef ctime
|
|
|
|
|
#undef fopen
|
|
|
|
|
#undef link
|
|
|
|
|
#undef mkdir
|
|
|
|
|
#undef mktemp
|
|
|
|
|
#undef open
|
|
|
|
|
#undef rename
|
|
|
|
|
#undef rmdir
|
|
|
|
|
#undef unlink
|
|
|
|
|
|
|
|
|
|
#undef close
|
|
|
|
|
#undef dup
|
|
|
|
|
#undef dup2
|
|
|
|
|
#undef pipe
|
|
|
|
|
#undef read
|
|
|
|
|
#undef write
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1999-06-16 20:00:19 +00:00
|
|
|
|
#undef strerror
|
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
#include "lisp.h"
|
|
|
|
|
|
|
|
|
|
#include <pwd.h>
|
2003-11-22 23:01:18 +00:00
|
|
|
|
#include <grp.h>
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
2000-09-03 17:41:20 +00:00
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
#define _ANONYMOUS_UNION
|
|
|
|
|
#define _ANONYMOUS_STRUCT
|
|
|
|
|
#endif
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#include <windows.h>
|
2008-08-15 12:49:09 +00:00
|
|
|
|
/* Some versions of compiler define MEMORYSTATUSEX, some don't, so we
|
|
|
|
|
use a different name to avoid compilation problems. */
|
|
|
|
|
typedef struct _MEMORY_STATUS_EX {
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
DWORD dwLength;
|
|
|
|
|
DWORD dwMemoryLoad;
|
|
|
|
|
DWORDLONG ullTotalPhys;
|
|
|
|
|
DWORDLONG ullAvailPhys;
|
|
|
|
|
DWORDLONG ullTotalPageFile;
|
|
|
|
|
DWORDLONG ullAvailPageFile;
|
|
|
|
|
DWORDLONG ullTotalVirtual;
|
|
|
|
|
DWORDLONG ullAvailVirtual;
|
|
|
|
|
DWORDLONG ullAvailExtendedVirtual;
|
2008-08-15 12:49:09 +00:00
|
|
|
|
} MEMORY_STATUS_EX,*LPMEMORY_STATUS_EX;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
2008-02-16 17:05:24 +00:00
|
|
|
|
#include <lmcons.h>
|
2005-07-14 22:32:50 +00:00
|
|
|
|
#include <shlobj.h>
|
1996-01-21 00:31:34 +00:00
|
|
|
|
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
#include <tlhelp32.h>
|
|
|
|
|
#include <psapi.h>
|
|
|
|
|
/* This either is not in psapi.h or guarded by higher value of
|
|
|
|
|
_WIN32_WINNT than what we use. */
|
|
|
|
|
typedef struct _PROCESS_MEMORY_COUNTERS_EX {
|
|
|
|
|
DWORD cb;
|
|
|
|
|
DWORD PageFaultCount;
|
|
|
|
|
DWORD PeakWorkingSetSize;
|
|
|
|
|
DWORD WorkingSetSize;
|
|
|
|
|
DWORD QuotaPeakPagedPoolUsage;
|
|
|
|
|
DWORD QuotaPagedPoolUsage;
|
|
|
|
|
DWORD QuotaPeakNonPagedPoolUsage;
|
|
|
|
|
DWORD QuotaNonPagedPoolUsage;
|
|
|
|
|
DWORD PagefileUsage;
|
|
|
|
|
DWORD PeakPagefileUsage;
|
|
|
|
|
DWORD PrivateUsage;
|
|
|
|
|
} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
|
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
#undef socket
|
|
|
|
|
#undef bind
|
|
|
|
|
#undef connect
|
|
|
|
|
#undef htons
|
|
|
|
|
#undef ntohs
|
|
|
|
|
#undef inet_addr
|
|
|
|
|
#undef gethostname
|
|
|
|
|
#undef gethostbyname
|
|
|
|
|
#undef getservbyname
|
2002-05-03 20:40:03 +00:00
|
|
|
|
#undef getpeername
|
1997-07-10 20:10:09 +00:00
|
|
|
|
#undef shutdown
|
2002-03-20 20:38:44 +00:00
|
|
|
|
#undef setsockopt
|
|
|
|
|
#undef listen
|
|
|
|
|
#undef getsockname
|
|
|
|
|
#undef accept
|
|
|
|
|
#undef recvfrom
|
|
|
|
|
#undef sendto
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif
|
1996-01-21 00:31:34 +00:00
|
|
|
|
|
1996-11-19 07:04:49 +00:00
|
|
|
|
#include "w32.h"
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#include "ndir.h"
|
1996-11-19 07:04:49 +00:00
|
|
|
|
#include "w32heap.h"
|
2001-01-13 00:00:26 +00:00
|
|
|
|
#include "systime.h"
|
2008-05-24 08:39:34 +00:00
|
|
|
|
#include "dispextern.h" /* for xstrcasecmp */
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
#include "coding.h" /* for Vlocale_coding_system */
|
2001-01-13 00:00:26 +00:00
|
|
|
|
|
2008-06-14 19:14:01 +00:00
|
|
|
|
/* For serial_configure and serial_open. */
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
#include "process.h"
|
|
|
|
|
/* From process.c */
|
|
|
|
|
extern Lisp_Object QCport, QCspeed, QCprocess;
|
|
|
|
|
extern Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
|
|
|
|
|
extern Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
|
|
|
|
|
|
2005-07-14 22:32:50 +00:00
|
|
|
|
typedef HRESULT (WINAPI * ShGetFolderPath_fn)
|
|
|
|
|
(IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
|
|
|
|
|
|
2002-12-18 06:16:28 +00:00
|
|
|
|
void globals_of_w32 ();
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
static DWORD get_rid (PSID);
|
2002-12-18 06:16:28 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
extern Lisp_Object Vw32_downcase_file_names;
|
|
|
|
|
extern Lisp_Object Vw32_generate_fake_inodes;
|
|
|
|
|
extern Lisp_Object Vw32_get_true_file_attributes;
|
2008-04-10 10:42:22 +00:00
|
|
|
|
/* Defined in process.c for its own purpose. */
|
|
|
|
|
extern Lisp_Object Qlocal;
|
|
|
|
|
|
2004-05-17 21:33:16 +00:00
|
|
|
|
extern int w32_num_mouse_buttons;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
|
2008-02-23 13:38:12 +00:00
|
|
|
|
/* Initialization states.
|
|
|
|
|
|
|
|
|
|
WARNING: If you add any more such variables for additional APIs,
|
|
|
|
|
you MUST add initialization for them to globals_of_w32
|
|
|
|
|
below. This is because these variables might get set
|
|
|
|
|
to non-NULL values during dumping, but the dumped Emacs
|
|
|
|
|
cannot reuse those values, because it could be run on a
|
|
|
|
|
different version of the OS, where API addresses are
|
|
|
|
|
different. */
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static BOOL g_b_init_is_windows_9x;
|
|
|
|
|
static BOOL g_b_init_open_process_token;
|
|
|
|
|
static BOOL g_b_init_get_token_information;
|
|
|
|
|
static BOOL g_b_init_lookup_account_sid;
|
|
|
|
|
static BOOL g_b_init_get_sid_identifier_authority;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
static BOOL g_b_init_get_sid_sub_authority;
|
|
|
|
|
static BOOL g_b_init_get_sid_sub_authority_count;
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
static BOOL g_b_init_get_file_security;
|
|
|
|
|
static BOOL g_b_init_get_security_descriptor_owner;
|
|
|
|
|
static BOOL g_b_init_get_security_descriptor_group;
|
|
|
|
|
static BOOL g_b_init_is_valid_sid;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
static BOOL g_b_init_create_toolhelp32_snapshot;
|
|
|
|
|
static BOOL g_b_init_process32_first;
|
|
|
|
|
static BOOL g_b_init_process32_next;
|
|
|
|
|
static BOOL g_b_init_open_thread_token;
|
|
|
|
|
static BOOL g_b_init_impersonate_self;
|
|
|
|
|
static BOOL g_b_init_revert_to_self;
|
|
|
|
|
static BOOL g_b_init_get_process_memory_info;
|
|
|
|
|
static BOOL g_b_init_get_process_working_set_size;
|
|
|
|
|
static BOOL g_b_init_global_memory_status;
|
|
|
|
|
static BOOL g_b_init_global_memory_status_ex;
|
2008-08-15 16:00:19 +00:00
|
|
|
|
static BOOL g_b_init_get_length_sid;
|
|
|
|
|
static BOOL g_b_init_equal_sid;
|
|
|
|
|
static BOOL g_b_init_copy_sid;
|
2009-07-04 10:43:10 +00:00
|
|
|
|
static BOOL g_b_init_get_native_system_info;
|
|
|
|
|
static BOOL g_b_init_get_system_times;
|
2002-12-18 06:16:28 +00:00
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
/*
|
|
|
|
|
BEGIN: Wrapper functions around OpenProcessToken
|
|
|
|
|
and other functions in advapi32.dll that are only
|
|
|
|
|
supported in Windows NT / 2k / XP
|
|
|
|
|
*/
|
|
|
|
|
/* ** Function pointer typedefs ** */
|
|
|
|
|
typedef BOOL (WINAPI * OpenProcessToken_Proc) (
|
|
|
|
|
HANDLE ProcessHandle,
|
|
|
|
|
DWORD DesiredAccess,
|
|
|
|
|
PHANDLE TokenHandle);
|
|
|
|
|
typedef BOOL (WINAPI * GetTokenInformation_Proc) (
|
|
|
|
|
HANDLE TokenHandle,
|
|
|
|
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
|
|
|
|
LPVOID TokenInformation,
|
|
|
|
|
DWORD TokenInformationLength,
|
|
|
|
|
PDWORD ReturnLength);
|
2007-06-14 15:58:13 +00:00
|
|
|
|
typedef BOOL (WINAPI * GetProcessTimes_Proc) (
|
|
|
|
|
HANDLE process_handle,
|
|
|
|
|
LPFILETIME creation_time,
|
|
|
|
|
LPFILETIME exit_time,
|
|
|
|
|
LPFILETIME kernel_time,
|
|
|
|
|
LPFILETIME user_time);
|
|
|
|
|
|
|
|
|
|
GetProcessTimes_Proc get_process_times_fn = NULL;
|
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
#ifdef _UNICODE
|
|
|
|
|
const char * const LookupAccountSid_Name = "LookupAccountSidW";
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
const char * const GetFileSecurity_Name = "GetFileSecurityW";
|
2002-11-17 22:35:26 +00:00
|
|
|
|
#else
|
|
|
|
|
const char * const LookupAccountSid_Name = "LookupAccountSidA";
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
const char * const GetFileSecurity_Name = "GetFileSecurityA";
|
2002-11-17 22:35:26 +00:00
|
|
|
|
#endif
|
|
|
|
|
typedef BOOL (WINAPI * LookupAccountSid_Proc) (
|
|
|
|
|
LPCTSTR lpSystemName,
|
|
|
|
|
PSID Sid,
|
|
|
|
|
LPTSTR Name,
|
|
|
|
|
LPDWORD cbName,
|
|
|
|
|
LPTSTR DomainName,
|
|
|
|
|
LPDWORD cbDomainName,
|
|
|
|
|
PSID_NAME_USE peUse);
|
|
|
|
|
typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
|
|
|
|
|
PSID pSid);
|
2008-01-26 13:04:14 +00:00
|
|
|
|
typedef PDWORD (WINAPI * GetSidSubAuthority_Proc) (
|
|
|
|
|
PSID pSid,
|
|
|
|
|
DWORD n);
|
|
|
|
|
typedef PUCHAR (WINAPI * GetSidSubAuthorityCount_Proc) (
|
|
|
|
|
PSID pSid);
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
typedef BOOL (WINAPI * GetFileSecurity_Proc) (
|
|
|
|
|
LPCTSTR lpFileName,
|
|
|
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
DWORD nLength,
|
|
|
|
|
LPDWORD lpnLengthNeeded);
|
|
|
|
|
typedef BOOL (WINAPI * GetSecurityDescriptorOwner_Proc) (
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
PSID *pOwner,
|
|
|
|
|
LPBOOL lpbOwnerDefaulted);
|
|
|
|
|
typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
PSID *pGroup,
|
|
|
|
|
LPBOOL lpbGroupDefaulted);
|
|
|
|
|
typedef BOOL (WINAPI * IsValidSid_Proc) (
|
|
|
|
|
PSID sid);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
|
|
|
|
|
DWORD dwFlags,
|
|
|
|
|
DWORD th32ProcessID);
|
|
|
|
|
typedef BOOL (WINAPI * Process32First_Proc) (
|
|
|
|
|
HANDLE hSnapshot,
|
|
|
|
|
LPPROCESSENTRY32 lppe);
|
|
|
|
|
typedef BOOL (WINAPI * Process32Next_Proc) (
|
|
|
|
|
HANDLE hSnapshot,
|
|
|
|
|
LPPROCESSENTRY32 lppe);
|
|
|
|
|
typedef BOOL (WINAPI * OpenThreadToken_Proc) (
|
|
|
|
|
HANDLE ThreadHandle,
|
|
|
|
|
DWORD DesiredAccess,
|
|
|
|
|
BOOL OpenAsSelf,
|
|
|
|
|
PHANDLE TokenHandle);
|
|
|
|
|
typedef BOOL (WINAPI * ImpersonateSelf_Proc) (
|
|
|
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel);
|
|
|
|
|
typedef BOOL (WINAPI * RevertToSelf_Proc) (void);
|
|
|
|
|
typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
|
|
|
|
|
HANDLE Process,
|
|
|
|
|
PPROCESS_MEMORY_COUNTERS ppsmemCounters,
|
|
|
|
|
DWORD cb);
|
|
|
|
|
typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
|
|
|
|
|
HANDLE hProcess,
|
|
|
|
|
DWORD * lpMinimumWorkingSetSize,
|
|
|
|
|
DWORD * lpMaximumWorkingSetSize);
|
|
|
|
|
typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
|
|
|
|
|
LPMEMORYSTATUS lpBuffer);
|
|
|
|
|
typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
|
2008-08-15 12:49:09 +00:00
|
|
|
|
LPMEMORY_STATUS_EX lpBuffer);
|
2008-08-15 16:00:19 +00:00
|
|
|
|
typedef BOOL (WINAPI * CopySid_Proc) (
|
|
|
|
|
DWORD nDestinationSidLength,
|
|
|
|
|
PSID pDestinationSid,
|
|
|
|
|
PSID pSourceSid);
|
|
|
|
|
typedef BOOL (WINAPI * EqualSid_Proc) (
|
|
|
|
|
PSID pSid1,
|
|
|
|
|
PSID pSid2);
|
|
|
|
|
typedef DWORD (WINAPI * GetLengthSid_Proc) (
|
|
|
|
|
PSID pSid);
|
2009-07-04 10:43:10 +00:00
|
|
|
|
typedef void (WINAPI * GetNativeSystemInfo_Proc) (
|
|
|
|
|
LPSYSTEM_INFO lpSystemInfo);
|
|
|
|
|
typedef BOOL (WINAPI * GetSystemTimes_Proc) (
|
|
|
|
|
LPFILETIME lpIdleTime,
|
|
|
|
|
LPFILETIME lpKernelTime,
|
|
|
|
|
LPFILETIME lpUserTime);
|
2008-08-15 16:00:19 +00:00
|
|
|
|
|
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
|
|
|
|
|
/* ** A utility function ** */
|
2006-12-27 21:55:59 +00:00
|
|
|
|
static BOOL
|
|
|
|
|
is_windows_9x ()
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static BOOL s_b_ret=0;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
OSVERSIONINFO os_ver;
|
2002-12-18 06:16:28 +00:00
|
|
|
|
if (g_b_init_is_windows_9x == 0)
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
g_b_init_is_windows_9x = 1;
|
|
|
|
|
ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
|
|
|
|
|
os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
|
if (GetVersionEx (&os_ver))
|
|
|
|
|
{
|
|
|
|
|
s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
|
|
|
|
|
}
|
2002-11-17 22:35:26 +00:00
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
return s_b_ret;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-06-14 15:58:13 +00:00
|
|
|
|
/* Get total user and system times for get-internal-run-time.
|
|
|
|
|
Returns a list of three integers if the times are provided by the OS
|
|
|
|
|
(NT derivatives), otherwise it returns the result of current-time. */
|
|
|
|
|
Lisp_Object
|
|
|
|
|
w32_get_internal_run_time ()
|
|
|
|
|
{
|
|
|
|
|
if (get_process_times_fn)
|
|
|
|
|
{
|
|
|
|
|
FILETIME create, exit, kernel, user;
|
|
|
|
|
HANDLE proc = GetCurrentProcess();
|
|
|
|
|
if ((*get_process_times_fn) (proc, &create, &exit, &kernel, &user))
|
|
|
|
|
{
|
|
|
|
|
LARGE_INTEGER user_int, kernel_int, total;
|
|
|
|
|
int microseconds;
|
|
|
|
|
user_int.LowPart = user.dwLowDateTime;
|
|
|
|
|
user_int.HighPart = user.dwHighDateTime;
|
|
|
|
|
kernel_int.LowPart = kernel.dwLowDateTime;
|
|
|
|
|
kernel_int.HighPart = kernel.dwHighDateTime;
|
|
|
|
|
total.QuadPart = user_int.QuadPart + kernel_int.QuadPart;
|
|
|
|
|
/* FILETIME is 100 nanosecond increments, Emacs only wants
|
|
|
|
|
microsecond resolution. */
|
|
|
|
|
total.QuadPart /= 10;
|
|
|
|
|
microseconds = total.QuadPart % 1000000;
|
|
|
|
|
total.QuadPart /= 1000000;
|
|
|
|
|
|
|
|
|
|
/* Sanity check to make sure we can represent the result. */
|
|
|
|
|
if (total.HighPart == 0)
|
|
|
|
|
{
|
|
|
|
|
int secs = total.LowPart;
|
|
|
|
|
|
|
|
|
|
return list3 (make_number ((secs >> 16) & 0xffff),
|
|
|
|
|
make_number (secs & 0xffff),
|
|
|
|
|
make_number (microseconds));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Fcurrent_time ();
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
/* ** The wrapper functions ** */
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI open_process_token (
|
|
|
|
|
HANDLE ProcessHandle,
|
|
|
|
|
DWORD DesiredAccess,
|
|
|
|
|
PHANDLE TokenHandle)
|
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
if (g_b_init_open_process_token == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_open_process_token = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Open_Process_Token =
|
|
|
|
|
(OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Open_Process_Token == NULL)
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (
|
2002-12-18 06:16:28 +00:00
|
|
|
|
s_pfn_Open_Process_Token (
|
2002-11-17 22:35:26 +00:00
|
|
|
|
ProcessHandle,
|
|
|
|
|
DesiredAccess,
|
|
|
|
|
TokenHandle)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_token_information (
|
|
|
|
|
HANDLE TokenHandle,
|
|
|
|
|
TOKEN_INFORMATION_CLASS TokenInformationClass,
|
|
|
|
|
LPVOID TokenInformation,
|
|
|
|
|
DWORD TokenInformationLength,
|
|
|
|
|
PDWORD ReturnLength)
|
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
if (g_b_init_get_token_information == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_token_information = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Token_Information =
|
|
|
|
|
(GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Token_Information == NULL)
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (
|
2002-12-18 06:16:28 +00:00
|
|
|
|
s_pfn_Get_Token_Information (
|
2002-11-17 22:35:26 +00:00
|
|
|
|
TokenHandle,
|
|
|
|
|
TokenInformationClass,
|
|
|
|
|
TokenInformation,
|
|
|
|
|
TokenInformationLength,
|
|
|
|
|
ReturnLength)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI lookup_account_sid (
|
|
|
|
|
LPCTSTR lpSystemName,
|
|
|
|
|
PSID Sid,
|
|
|
|
|
LPTSTR Name,
|
|
|
|
|
LPDWORD cbName,
|
|
|
|
|
LPTSTR DomainName,
|
|
|
|
|
LPDWORD cbDomainName,
|
|
|
|
|
PSID_NAME_USE peUse)
|
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
if (g_b_init_lookup_account_sid == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_lookup_account_sid = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Lookup_Account_Sid =
|
|
|
|
|
(LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Lookup_Account_Sid == NULL)
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (
|
2002-12-18 06:16:28 +00:00
|
|
|
|
s_pfn_Lookup_Account_Sid (
|
2002-11-17 22:35:26 +00:00
|
|
|
|
lpSystemName,
|
|
|
|
|
Sid,
|
|
|
|
|
Name,
|
|
|
|
|
cbName,
|
|
|
|
|
DomainName,
|
|
|
|
|
cbDomainName,
|
|
|
|
|
peUse)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
|
|
|
|
|
PSID pSid)
|
|
|
|
|
{
|
2002-12-18 06:16:28 +00:00
|
|
|
|
static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
|
2002-11-17 22:35:26 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
if (g_b_init_get_sid_identifier_authority == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_sid_identifier_authority = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Sid_Identifier_Authority =
|
|
|
|
|
(GetSidIdentifierAuthority_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetSidIdentifierAuthority");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Sid_Identifier_Authority == NULL)
|
2002-11-17 22:35:26 +00:00
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2002-12-18 06:16:28 +00:00
|
|
|
|
return (s_pfn_Get_Sid_Identifier_Authority (pSid));
|
2002-11-17 22:35:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-01-26 13:04:14 +00:00
|
|
|
|
PDWORD WINAPI get_sid_sub_authority (
|
|
|
|
|
PSID pSid,
|
|
|
|
|
DWORD n)
|
|
|
|
|
{
|
|
|
|
|
static GetSidSubAuthority_Proc s_pfn_Get_Sid_Sub_Authority = NULL;
|
2008-01-26 15:04:33 +00:00
|
|
|
|
static DWORD zero = 0U;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
2008-01-26 15:04:33 +00:00
|
|
|
|
return &zero;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_sid_sub_authority == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_sid_sub_authority = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Sid_Sub_Authority =
|
|
|
|
|
(GetSidSubAuthority_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetSidSubAuthority");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Sid_Sub_Authority == NULL)
|
|
|
|
|
{
|
2008-01-26 15:04:33 +00:00
|
|
|
|
return &zero;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_Sid_Sub_Authority (pSid, n));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PUCHAR WINAPI get_sid_sub_authority_count (
|
|
|
|
|
PSID pSid)
|
|
|
|
|
{
|
|
|
|
|
static GetSidSubAuthorityCount_Proc s_pfn_Get_Sid_Sub_Authority_Count = NULL;
|
2008-01-26 15:04:33 +00:00
|
|
|
|
static UCHAR zero = 0U;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
2008-01-26 15:04:33 +00:00
|
|
|
|
return &zero;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_sid_sub_authority_count == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_sid_sub_authority_count = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Sid_Sub_Authority_Count =
|
|
|
|
|
(GetSidSubAuthorityCount_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetSidSubAuthorityCount");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Sid_Sub_Authority_Count == NULL)
|
|
|
|
|
{
|
2008-01-26 15:04:33 +00:00
|
|
|
|
return &zero;
|
2008-01-26 13:04:14 +00:00
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_Sid_Sub_Authority_Count (pSid));
|
|
|
|
|
}
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
BOOL WINAPI get_file_security (
|
|
|
|
|
LPCTSTR lpFileName,
|
|
|
|
|
SECURITY_INFORMATION RequestedInformation,
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
DWORD nLength,
|
|
|
|
|
LPDWORD lpnLengthNeeded)
|
|
|
|
|
{
|
|
|
|
|
static GetFileSecurity_Proc s_pfn_Get_File_Security = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_file_security == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_file_security = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_File_Security =
|
|
|
|
|
(GetFileSecurity_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, GetFileSecurity_Name);
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_File_Security == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_File_Security (lpFileName, RequestedInformation,
|
|
|
|
|
pSecurityDescriptor, nLength,
|
|
|
|
|
lpnLengthNeeded));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_security_descriptor_owner (
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
PSID *pOwner,
|
|
|
|
|
LPBOOL lpbOwnerDefaulted)
|
|
|
|
|
{
|
|
|
|
|
static GetSecurityDescriptorOwner_Proc s_pfn_Get_Security_Descriptor_Owner = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_security_descriptor_owner == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_security_descriptor_owner = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Security_Descriptor_Owner =
|
|
|
|
|
(GetSecurityDescriptorOwner_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetSecurityDescriptorOwner");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Security_Descriptor_Owner == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_Security_Descriptor_Owner (pSecurityDescriptor, pOwner,
|
|
|
|
|
lpbOwnerDefaulted));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_security_descriptor_group (
|
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor,
|
|
|
|
|
PSID *pGroup,
|
|
|
|
|
LPBOOL lpbGroupDefaulted)
|
|
|
|
|
{
|
|
|
|
|
static GetSecurityDescriptorGroup_Proc s_pfn_Get_Security_Descriptor_Group = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_security_descriptor_group == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_security_descriptor_group = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Security_Descriptor_Group =
|
|
|
|
|
(GetSecurityDescriptorGroup_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetSecurityDescriptorGroup");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Security_Descriptor_Group == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_Security_Descriptor_Group (pSecurityDescriptor, pGroup,
|
|
|
|
|
lpbGroupDefaulted));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI is_valid_sid (
|
|
|
|
|
PSID sid)
|
|
|
|
|
{
|
|
|
|
|
static IsValidSid_Proc s_pfn_Is_Valid_Sid = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_is_valid_sid == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_is_valid_sid = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Is_Valid_Sid =
|
|
|
|
|
(IsValidSid_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "IsValidSid");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Is_Valid_Sid == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Is_Valid_Sid (sid));
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-15 16:00:19 +00:00
|
|
|
|
BOOL WINAPI equal_sid (
|
|
|
|
|
PSID sid1,
|
|
|
|
|
PSID sid2)
|
|
|
|
|
{
|
|
|
|
|
static EqualSid_Proc s_pfn_Equal_Sid = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_equal_sid == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_equal_sid = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Equal_Sid =
|
|
|
|
|
(EqualSid_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "EqualSid");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Equal_Sid == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Equal_Sid (sid1, sid2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI get_length_sid (
|
|
|
|
|
PSID sid)
|
|
|
|
|
{
|
|
|
|
|
static GetLengthSid_Proc s_pfn_Get_Length_Sid = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_length_sid == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_length_sid = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Get_Length_Sid =
|
|
|
|
|
(GetLengthSid_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "GetLengthSid");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Length_Sid == NULL)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Get_Length_Sid (sid));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI copy_sid (
|
|
|
|
|
DWORD destlen,
|
|
|
|
|
PSID dest,
|
|
|
|
|
PSID src)
|
|
|
|
|
{
|
|
|
|
|
static CopySid_Proc s_pfn_Copy_Sid = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_copy_sid == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_copy_sid = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Copy_Sid =
|
|
|
|
|
(CopySid_Proc) GetProcAddress (
|
|
|
|
|
hm_advapi32, "CopySid");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Copy_Sid == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Copy_Sid (destlen, dest, src));
|
|
|
|
|
}
|
|
|
|
|
|
2002-11-17 22:35:26 +00:00
|
|
|
|
/*
|
|
|
|
|
END: Wrapper functions around OpenProcessToken
|
|
|
|
|
and other functions in advapi32.dll that are only
|
|
|
|
|
supported in Windows NT / 2k / XP
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-04 10:43:10 +00:00
|
|
|
|
void WINAPI get_native_system_info (
|
|
|
|
|
LPSYSTEM_INFO lpSystemInfo)
|
|
|
|
|
{
|
|
|
|
|
static GetNativeSystemInfo_Proc s_pfn_Get_Native_System_Info = NULL;
|
|
|
|
|
if (is_windows_9x () != TRUE)
|
|
|
|
|
{
|
|
|
|
|
if (g_b_init_get_native_system_info == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_native_system_info = 1;
|
|
|
|
|
s_pfn_Get_Native_System_Info =
|
|
|
|
|
(GetNativeSystemInfo_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"GetNativeSystemInfo");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Native_System_Info != NULL)
|
|
|
|
|
s_pfn_Get_Native_System_Info (lpSystemInfo);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
lpSystemInfo->dwNumberOfProcessors = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_system_times(
|
|
|
|
|
LPFILETIME lpIdleTime,
|
|
|
|
|
LPFILETIME lpKernelTime,
|
|
|
|
|
LPFILETIME lpUserTime)
|
|
|
|
|
{
|
|
|
|
|
static GetSystemTimes_Proc s_pfn_Get_System_times = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_system_times == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_system_times = 1;
|
|
|
|
|
s_pfn_Get_System_times =
|
|
|
|
|
(GetSystemTimes_Proc)GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"GetSystemTimes");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_System_times == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
return (s_pfn_Get_System_times (lpIdleTime, lpKernelTime, lpUserTime));
|
|
|
|
|
}
|
2000-12-18 23:50:26 +00:00
|
|
|
|
|
|
|
|
|
/* Equivalent of strerror for W32 error codes. */
|
|
|
|
|
char *
|
|
|
|
|
w32_strerror (int error_no)
|
|
|
|
|
{
|
|
|
|
|
static char buf[500];
|
|
|
|
|
|
|
|
|
|
if (error_no == 0)
|
|
|
|
|
error_no = GetLastError ();
|
|
|
|
|
|
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
|
|
|
|
|
error_no,
|
|
|
|
|
0, /* choose most suitable language */
|
|
|
|
|
buf, sizeof (buf), NULL))
|
|
|
|
|
sprintf (buf, "w32 error %u", error_no);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-05 13:01:10 +00:00
|
|
|
|
/* Return 1 if P is a valid pointer to an object of size SIZE. Return
|
|
|
|
|
0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
|
|
|
|
|
|
|
|
|
|
This is called from alloc.c:valid_pointer_p. */
|
|
|
|
|
int
|
|
|
|
|
w32_valid_pointer_p (void *p, int size)
|
|
|
|
|
{
|
|
|
|
|
SIZE_T done;
|
|
|
|
|
HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
|
|
|
|
|
|
|
|
|
|
if (h)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *buf = alloca (size);
|
|
|
|
|
int retval = ReadProcessMemory (h, p, buf, size, &done);
|
|
|
|
|
|
|
|
|
|
CloseHandle (h);
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
static char startup_dir[MAXPATHLEN];
|
1996-01-21 00:31:34 +00:00
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
/* Get the current working directory. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
char *
|
1994-11-01 10:27:02 +00:00
|
|
|
|
getwd (char *dir)
|
|
|
|
|
{
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#if 0
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
|
|
|
|
|
return dir;
|
|
|
|
|
return NULL;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#else
|
|
|
|
|
/* Emacs doesn't actually change directory itself, and we want to
|
|
|
|
|
force our real wd to be where emacs.exe is to avoid unnecessary
|
|
|
|
|
conflicts when trying to rename or delete directories. */
|
|
|
|
|
strcpy (dir, startup_dir);
|
|
|
|
|
return dir;
|
|
|
|
|
#endif
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifndef HAVE_SOCKETS
|
1994-11-01 10:27:02 +00:00
|
|
|
|
/* Emulate gethostname. */
|
|
|
|
|
int
|
|
|
|
|
gethostname (char *buffer, int size)
|
|
|
|
|
{
|
2003-02-04 14:56:31 +00:00
|
|
|
|
/* NT only allows small host names, so the buffer is
|
1994-11-01 10:27:02 +00:00
|
|
|
|
certainly large enough. */
|
|
|
|
|
return !GetComputerName (buffer, &size);
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif /* HAVE_SOCKETS */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
|
|
|
|
/* Emulate getloadavg. */
|
2009-07-04 10:43:10 +00:00
|
|
|
|
|
|
|
|
|
struct load_sample {
|
|
|
|
|
time_t sample_time;
|
|
|
|
|
ULONGLONG idle;
|
|
|
|
|
ULONGLONG kernel;
|
|
|
|
|
ULONGLONG user;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Number of processors on this machine. */
|
|
|
|
|
static unsigned num_of_processors;
|
|
|
|
|
|
|
|
|
|
/* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
|
|
|
|
|
static struct load_sample samples[16*60];
|
|
|
|
|
static int first_idx = -1, last_idx = -1;
|
|
|
|
|
static int max_idx = sizeof (samples) / sizeof (samples[0]);
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
buf_next (int from)
|
|
|
|
|
{
|
|
|
|
|
int next_idx = from + 1;
|
|
|
|
|
|
|
|
|
|
if (next_idx >= max_idx)
|
|
|
|
|
next_idx = 0;
|
|
|
|
|
|
|
|
|
|
return next_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
buf_prev (int from)
|
|
|
|
|
{
|
|
|
|
|
int prev_idx = from - 1;
|
|
|
|
|
|
|
|
|
|
if (prev_idx < 0)
|
|
|
|
|
prev_idx = max_idx - 1;
|
|
|
|
|
|
|
|
|
|
return prev_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
sample_system_load (ULONGLONG *idle, ULONGLONG *kernel, ULONGLONG *user)
|
|
|
|
|
{
|
|
|
|
|
SYSTEM_INFO sysinfo;
|
|
|
|
|
FILETIME ft_idle, ft_user, ft_kernel;
|
|
|
|
|
|
|
|
|
|
/* Initialize the number of processors on this machine. */
|
|
|
|
|
if (num_of_processors <= 0)
|
|
|
|
|
{
|
|
|
|
|
get_native_system_info (&sysinfo);
|
|
|
|
|
num_of_processors = sysinfo.dwNumberOfProcessors;
|
|
|
|
|
if (num_of_processors <= 0)
|
|
|
|
|
{
|
|
|
|
|
GetSystemInfo (&sysinfo);
|
|
|
|
|
num_of_processors = sysinfo.dwNumberOfProcessors;
|
|
|
|
|
}
|
|
|
|
|
if (num_of_processors <= 0)
|
|
|
|
|
num_of_processors = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO: Take into account threads that are ready to run, by
|
|
|
|
|
sampling the "\System\Processor Queue Length" performance
|
|
|
|
|
counter. The code below accounts only for threads that are
|
|
|
|
|
actually running. */
|
|
|
|
|
|
|
|
|
|
if (get_system_times (&ft_idle, &ft_kernel, &ft_user))
|
|
|
|
|
{
|
|
|
|
|
ULARGE_INTEGER uidle, ukernel, uuser;
|
|
|
|
|
|
|
|
|
|
memcpy (&uidle, &ft_idle, sizeof (ft_idle));
|
|
|
|
|
memcpy (&ukernel, &ft_kernel, sizeof (ft_kernel));
|
|
|
|
|
memcpy (&uuser, &ft_user, sizeof (ft_user));
|
|
|
|
|
*idle = uidle.QuadPart;
|
|
|
|
|
*kernel = ukernel.QuadPart;
|
|
|
|
|
*user = uuser.QuadPart;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*idle = 0;
|
|
|
|
|
*kernel = 0;
|
|
|
|
|
*user = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Produce the load average for a given time interval, using the
|
|
|
|
|
samples in the samples[] array. WHICH can be 0, 1, or 2, meaning
|
|
|
|
|
1-minute, 5-minute, or 15-minute average, respectively. */
|
|
|
|
|
static double
|
|
|
|
|
getavg (int which)
|
|
|
|
|
{
|
|
|
|
|
double retval = -1.0;
|
|
|
|
|
double tdiff;
|
|
|
|
|
int idx;
|
|
|
|
|
double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
|
|
|
|
|
time_t now = samples[last_idx].sample_time;
|
|
|
|
|
|
|
|
|
|
if (first_idx != last_idx)
|
|
|
|
|
{
|
|
|
|
|
for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
|
|
|
|
|
{
|
|
|
|
|
tdiff = difftime (now, samples[idx].sample_time);
|
|
|
|
|
if (tdiff >= span - 2*DBL_EPSILON*now)
|
|
|
|
|
{
|
|
|
|
|
long double sys =
|
|
|
|
|
samples[last_idx].kernel + samples[last_idx].user
|
|
|
|
|
- (samples[idx].kernel + samples[idx].user);
|
|
|
|
|
long double idl = samples[last_idx].idle - samples[idx].idle;
|
|
|
|
|
|
|
|
|
|
retval = (1.0 - idl / sys) * num_of_processors;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (idx == first_idx)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
int
|
|
|
|
|
getloadavg (double loadavg[], int nelem)
|
|
|
|
|
{
|
2009-07-04 10:43:10 +00:00
|
|
|
|
int elem;
|
|
|
|
|
ULONGLONG idle, kernel, user;
|
|
|
|
|
time_t now = time (NULL);
|
|
|
|
|
|
|
|
|
|
/* Store another sample. We ignore samples that are less than 1 sec
|
|
|
|
|
apart. */
|
|
|
|
|
if (difftime (now, samples[last_idx].sample_time) >= 1.0 - 2*DBL_EPSILON*now)
|
|
|
|
|
{
|
|
|
|
|
sample_system_load (&idle, &kernel, &user);
|
|
|
|
|
last_idx = buf_next (last_idx);
|
|
|
|
|
samples[last_idx].sample_time = now;
|
|
|
|
|
samples[last_idx].idle = idle;
|
|
|
|
|
samples[last_idx].kernel = kernel;
|
|
|
|
|
samples[last_idx].user = user;
|
|
|
|
|
/* If the buffer has more that 15 min worth of samples, discard
|
|
|
|
|
the old ones. */
|
|
|
|
|
if (first_idx == -1)
|
|
|
|
|
first_idx = last_idx;
|
|
|
|
|
while (first_idx != last_idx
|
|
|
|
|
&& (difftime (now, samples[first_idx].sample_time)
|
|
|
|
|
>= 15.0*60 + 2*DBL_EPSILON*now))
|
|
|
|
|
first_idx = buf_next (first_idx);
|
|
|
|
|
}
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
2009-07-04 10:43:10 +00:00
|
|
|
|
for (elem = 0; elem < nelem; elem++)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
2009-07-04 10:43:10 +00:00
|
|
|
|
double avg = getavg (elem);
|
|
|
|
|
|
|
|
|
|
if (avg < 0)
|
|
|
|
|
break;
|
|
|
|
|
loadavg[elem] = avg;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
2009-07-04 10:43:10 +00:00
|
|
|
|
|
|
|
|
|
return elem;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Emulate getpwuid, getpwnam and others. */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1995-06-30 21:12:37 +00:00
|
|
|
|
#define PASSWD_FIELD_SIZE 256
|
|
|
|
|
|
2008-05-09 09:40:56 +00:00
|
|
|
|
static char dflt_passwd_name[PASSWD_FIELD_SIZE];
|
|
|
|
|
static char dflt_passwd_passwd[PASSWD_FIELD_SIZE];
|
|
|
|
|
static char dflt_passwd_gecos[PASSWD_FIELD_SIZE];
|
|
|
|
|
static char dflt_passwd_dir[PASSWD_FIELD_SIZE];
|
|
|
|
|
static char dflt_passwd_shell[PASSWD_FIELD_SIZE];
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
2008-05-09 09:40:56 +00:00
|
|
|
|
static struct passwd dflt_passwd =
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd_name,
|
|
|
|
|
dflt_passwd_passwd,
|
1994-11-01 10:27:02 +00:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd_gecos,
|
|
|
|
|
dflt_passwd_dir,
|
|
|
|
|
dflt_passwd_shell,
|
1994-11-01 10:27:02 +00:00
|
|
|
|
};
|
|
|
|
|
|
2008-05-09 09:40:56 +00:00
|
|
|
|
static char dflt_group_name[GNLEN+1];
|
|
|
|
|
|
|
|
|
|
static struct group dflt_group =
|
2003-11-22 23:01:18 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
/* When group information is not available, we return this as the
|
|
|
|
|
group for all files. */
|
|
|
|
|
dflt_group_name,
|
|
|
|
|
0,
|
2003-11-22 23:01:18 +00:00
|
|
|
|
};
|
|
|
|
|
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned
|
2003-02-04 14:56:31 +00:00
|
|
|
|
getuid ()
|
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
return dflt_passwd.pw_uid;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned
|
2003-02-04 14:56:31 +00:00
|
|
|
|
geteuid ()
|
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* I could imagine arguing for checking to see whether the user is
|
|
|
|
|
in the Administrators group and returning a UID of 0 for that
|
|
|
|
|
case, but I don't know how wise that would be in the long run. */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
return getuid ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned
|
2003-02-04 14:56:31 +00:00
|
|
|
|
getgid ()
|
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
return dflt_passwd.pw_gid;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned
|
2003-02-04 14:56:31 +00:00
|
|
|
|
getegid ()
|
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return getgid ();
|
|
|
|
|
}
|
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
struct passwd *
|
2009-03-21 11:31:50 +00:00
|
|
|
|
getpwuid (unsigned uid)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
if (uid == dflt_passwd.pw_uid)
|
|
|
|
|
return &dflt_passwd;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return NULL;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-11-22 23:01:18 +00:00
|
|
|
|
struct group *
|
|
|
|
|
getgrgid (gid_t gid)
|
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
return &dflt_group;
|
2003-11-22 23:01:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
struct passwd *
|
|
|
|
|
getpwnam (char *name)
|
|
|
|
|
{
|
|
|
|
|
struct passwd *pw;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
pw = getpwuid (getuid ());
|
|
|
|
|
if (!pw)
|
|
|
|
|
return pw;
|
|
|
|
|
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if (xstrcasecmp (name, pw->pw_name))
|
1994-11-01 10:27:02 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return pw;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
void
|
|
|
|
|
init_user_info ()
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Find the user's real name by opening the process token and
|
|
|
|
|
looking up the name associated with the user-sid in that token.
|
|
|
|
|
|
|
|
|
|
Use the relative portion of the identifier authority value from
|
|
|
|
|
the user-sid as the user id value (same for group id using the
|
|
|
|
|
primary group sid from the process token). */
|
|
|
|
|
|
2008-05-09 09:40:56 +00:00
|
|
|
|
char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
|
2008-08-30 16:46:54 +00:00
|
|
|
|
DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
|
2008-05-09 09:40:56 +00:00
|
|
|
|
DWORD glength = sizeof (gname);
|
2007-06-14 10:01:04 +00:00
|
|
|
|
HANDLE token = NULL;
|
|
|
|
|
SID_NAME_USE user_type;
|
2008-08-30 16:46:54 +00:00
|
|
|
|
unsigned char *buf = NULL;
|
|
|
|
|
DWORD blen = 0;
|
2008-02-16 17:05:24 +00:00
|
|
|
|
TOKEN_USER user_token;
|
|
|
|
|
TOKEN_PRIMARY_GROUP group_token;
|
2008-08-30 16:46:54 +00:00
|
|
|
|
BOOL result;
|
2007-06-14 10:01:04 +00:00
|
|
|
|
|
2008-08-30 16:46:54 +00:00
|
|
|
|
result = open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token);
|
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
result = get_token_information (token, TokenUser, NULL, 0, &blen);
|
|
|
|
|
if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
|
{
|
|
|
|
|
buf = xmalloc (blen);
|
|
|
|
|
result = get_token_information (token, TokenUser,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
memcpy (&user_token, buf, sizeof (user_token));
|
|
|
|
|
result = lookup_account_sid (NULL, user_token.User.Sid,
|
|
|
|
|
uname, &ulength,
|
|
|
|
|
domain, &dlength, &user_type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
result = FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (result)
|
1995-10-08 19:38:53 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
strcpy (dflt_passwd.pw_name, uname);
|
2008-01-26 13:04:14 +00:00
|
|
|
|
/* Determine a reasonable uid value. */
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if (xstrcasecmp ("administrator", uname) == 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd.pw_uid = 500; /* well-known Administrator uid */
|
|
|
|
|
dflt_passwd.pw_gid = 513; /* well-known None gid */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-01-26 14:52:01 +00:00
|
|
|
|
/* Use the last sub-authority value of the RID, the relative
|
|
|
|
|
portion of the SID, as user/group ID. */
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
dflt_passwd.pw_uid = get_rid (user_token.User.Sid);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
/* Get group id and name. */
|
2008-08-30 16:46:54 +00:00
|
|
|
|
result = get_token_information (token, TokenPrimaryGroup,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
|
{
|
|
|
|
|
buf = xrealloc (buf, blen = needed);
|
|
|
|
|
result = get_token_information (token, TokenPrimaryGroup,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
}
|
|
|
|
|
if (result)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2008-02-16 17:05:24 +00:00
|
|
|
|
memcpy (&group_token, buf, sizeof (group_token));
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
dflt_passwd.pw_gid = get_rid (group_token.PrimaryGroup);
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dlength = sizeof (domain);
|
2008-08-30 16:46:54 +00:00
|
|
|
|
/* If we can get at the real Primary Group name, use that.
|
|
|
|
|
Otherwise, the default group name was already set to
|
|
|
|
|
"None" in globals_of_w32. */
|
2008-05-09 09:40:56 +00:00
|
|
|
|
if (lookup_account_sid (NULL, group_token.PrimaryGroup,
|
|
|
|
|
gname, &glength, NULL, &dlength,
|
|
|
|
|
&user_type))
|
|
|
|
|
strcpy (dflt_group_name, gname);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd.pw_gid = dflt_passwd.pw_uid;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* If security calls are not supported (presumably because we
|
2008-08-30 16:46:54 +00:00
|
|
|
|
are running under Windows 9X), fallback to this: */
|
2008-05-09 09:40:56 +00:00
|
|
|
|
else if (GetUserName (uname, &ulength))
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
strcpy (dflt_passwd.pw_name, uname);
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if (xstrcasecmp ("administrator", uname) == 0)
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd.pw_uid = 0;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
else
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_passwd.pw_uid = 123;
|
|
|
|
|
dflt_passwd.pw_gid = dflt_passwd.pw_uid;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-05-09 09:40:56 +00:00
|
|
|
|
strcpy (dflt_passwd.pw_name, "unknown");
|
|
|
|
|
dflt_passwd.pw_uid = 123;
|
|
|
|
|
dflt_passwd.pw_gid = 123;
|
1995-10-08 19:38:53 +00:00
|
|
|
|
}
|
2008-05-09 09:40:56 +00:00
|
|
|
|
dflt_group.gr_gid = dflt_passwd.pw_gid;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Ensure HOME and SHELL are defined. */
|
|
|
|
|
if (getenv ("HOME") == NULL)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
abort ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (getenv ("SHELL") == NULL)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
abort ();
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Set dir and shell from environment variables. */
|
2008-05-09 09:40:56 +00:00
|
|
|
|
strcpy (dflt_passwd.pw_dir, getenv ("HOME"));
|
|
|
|
|
strcpy (dflt_passwd.pw_shell, getenv ("SHELL"));
|
1995-05-26 05:26:17 +00:00
|
|
|
|
|
2008-08-30 16:46:54 +00:00
|
|
|
|
xfree (buf);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (token)
|
|
|
|
|
CloseHandle (token);
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
1996-05-03 18:32:52 +00:00
|
|
|
|
random ()
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* rand () on NT gives us 15 random bits...hack together 30 bits. */
|
|
|
|
|
return ((rand () << 15) | rand ());
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
1996-05-03 18:32:52 +00:00
|
|
|
|
srandom (int seed)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
srand (seed);
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
1996-06-03 21:18:55 +00:00
|
|
|
|
/* Normalize filename by converting all path separators to
|
|
|
|
|
the specified separator. Also conditionally convert upper
|
|
|
|
|
case path name components to lower case. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
normalize_filename (fp, path_sep)
|
|
|
|
|
register char *fp;
|
|
|
|
|
char path_sep;
|
|
|
|
|
{
|
|
|
|
|
char sep;
|
|
|
|
|
char *elem;
|
|
|
|
|
|
1996-07-07 01:59:24 +00:00
|
|
|
|
/* Always lower-case drive letters a-z, even if the filesystem
|
|
|
|
|
preserves case in filenames.
|
|
|
|
|
This is so filenames can be compared by string comparison
|
|
|
|
|
functions that are case-sensitive. Even case-preserving filesystems
|
|
|
|
|
do not distinguish case in drive letters. */
|
|
|
|
|
if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
|
|
|
|
|
{
|
|
|
|
|
*fp += 'a' - 'A';
|
|
|
|
|
fp += 2;
|
|
|
|
|
}
|
|
|
|
|
|
1996-11-19 04:59:23 +00:00
|
|
|
|
if (NILP (Vw32_downcase_file_names))
|
1996-06-03 21:18:55 +00:00
|
|
|
|
{
|
|
|
|
|
while (*fp)
|
|
|
|
|
{
|
|
|
|
|
if (*fp == '/' || *fp == '\\')
|
|
|
|
|
*fp = path_sep;
|
|
|
|
|
fp++;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sep = path_sep; /* convert to this path separator */
|
|
|
|
|
elem = fp; /* start of current path element */
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
if (*fp >= 'a' && *fp <= 'z')
|
|
|
|
|
elem = 0; /* don't convert this element */
|
|
|
|
|
|
|
|
|
|
if (*fp == 0 || *fp == ':')
|
|
|
|
|
{
|
|
|
|
|
sep = *fp; /* restore current separator (or 0) */
|
|
|
|
|
*fp = '/'; /* after conversion of this element */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*fp == '/' || *fp == '\\')
|
|
|
|
|
{
|
|
|
|
|
if (elem && elem != fp)
|
|
|
|
|
{
|
|
|
|
|
*fp = 0; /* temporary end of string */
|
|
|
|
|
_strlwr (elem); /* while we convert to lower case */
|
|
|
|
|
}
|
|
|
|
|
*fp = sep; /* convert (or restore) path separator */
|
|
|
|
|
elem = fp + 1; /* next element starts after separator */
|
|
|
|
|
sep = path_sep;
|
|
|
|
|
}
|
|
|
|
|
} while (*fp++);
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Destructively turn backslashes into slashes. */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
void
|
1996-05-03 18:32:52 +00:00
|
|
|
|
dostounix_filename (p)
|
|
|
|
|
register char *p;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-06-03 21:18:55 +00:00
|
|
|
|
normalize_filename (p, '/');
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Destructively turn slashes into backslashes. */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
void
|
1996-05-03 18:32:52 +00:00
|
|
|
|
unixtodos_filename (p)
|
|
|
|
|
register char *p;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-06-03 21:18:55 +00:00
|
|
|
|
normalize_filename (p, '\\');
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Remove all CR's that are followed by a LF.
|
|
|
|
|
(From msdos.c...probably should figure out a way to share it,
|
|
|
|
|
although this code isn't going to ever change.) */
|
1995-04-12 02:10:10 +00:00
|
|
|
|
int
|
1996-05-03 18:32:52 +00:00
|
|
|
|
crlf_to_lf (n, buf)
|
|
|
|
|
register int n;
|
|
|
|
|
register unsigned char *buf;
|
1995-04-12 02:10:10 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
unsigned char *np = buf;
|
|
|
|
|
unsigned char *startp = buf;
|
|
|
|
|
unsigned char *endp = buf + n;
|
1995-04-12 02:10:10 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (n == 0)
|
|
|
|
|
return n;
|
|
|
|
|
while (buf < endp - 1)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (*buf == 0x0d)
|
|
|
|
|
{
|
|
|
|
|
if (*(++buf) != 0x0a)
|
|
|
|
|
*np++ = 0x0d;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*np++ = *buf++;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (buf < endp)
|
|
|
|
|
*np++ = *buf++;
|
|
|
|
|
return np - startp;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Parse the root part of file name, if present. Return length and
|
|
|
|
|
optionally store pointer to char after root. */
|
|
|
|
|
static int
|
|
|
|
|
parse_root (char * name, char ** pPath)
|
|
|
|
|
{
|
|
|
|
|
char * start = name;
|
|
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
/* find the root name of the volume if given */
|
|
|
|
|
if (isalpha (name[0]) && name[1] == ':')
|
|
|
|
|
{
|
|
|
|
|
/* skip past drive specifier */
|
|
|
|
|
name += 2;
|
|
|
|
|
if (IS_DIRECTORY_SEP (name[0]))
|
|
|
|
|
name++;
|
|
|
|
|
}
|
|
|
|
|
else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
|
|
|
|
|
{
|
|
|
|
|
int slashes = 2;
|
|
|
|
|
name += 2;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
|
|
|
|
|
break;
|
|
|
|
|
name++;
|
|
|
|
|
}
|
|
|
|
|
while ( *name );
|
|
|
|
|
if (IS_DIRECTORY_SEP (name[0]))
|
|
|
|
|
name++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pPath)
|
|
|
|
|
*pPath = name;
|
|
|
|
|
|
|
|
|
|
return name - start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get long base name for name; name is assumed to be absolute. */
|
|
|
|
|
static int
|
|
|
|
|
get_long_basename (char * name, char * buf, int size)
|
|
|
|
|
{
|
|
|
|
|
WIN32_FIND_DATA find_data;
|
|
|
|
|
HANDLE dir_handle;
|
|
|
|
|
int len = 0;
|
|
|
|
|
|
2000-05-16 14:29:08 +00:00
|
|
|
|
/* must be valid filename, no wild cards or other invalid characters */
|
2007-02-23 18:40:41 +00:00
|
|
|
|
if (_mbspbrk (name, "*?|<>\""))
|
1998-05-12 21:33:44 +00:00
|
|
|
|
return 0;
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
dir_handle = FindFirstFile (name, &find_data);
|
|
|
|
|
if (dir_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
if ((len = strlen (find_data.cFileName)) < size)
|
|
|
|
|
memcpy (buf, find_data.cFileName, len + 1);
|
|
|
|
|
else
|
|
|
|
|
len = 0;
|
|
|
|
|
FindClose (dir_handle);
|
|
|
|
|
}
|
|
|
|
|
return len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get long name for file, if possible (assumed to be absolute). */
|
|
|
|
|
BOOL
|
|
|
|
|
w32_get_long_filename (char * name, char * buf, int size)
|
|
|
|
|
{
|
|
|
|
|
char * o = buf;
|
|
|
|
|
char * p;
|
|
|
|
|
char * q;
|
|
|
|
|
char full[ MAX_PATH ];
|
|
|
|
|
int len;
|
|
|
|
|
|
|
|
|
|
len = strlen (name);
|
|
|
|
|
if (len >= MAX_PATH)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Use local copy for destructive modification. */
|
|
|
|
|
memcpy (full, name, len+1);
|
|
|
|
|
unixtodos_filename (full);
|
|
|
|
|
|
|
|
|
|
/* Copy root part verbatim. */
|
|
|
|
|
len = parse_root (full, &p);
|
|
|
|
|
memcpy (o, full, len);
|
|
|
|
|
o += len;
|
1998-12-10 05:43:07 +00:00
|
|
|
|
*o = '\0';
|
1997-09-03 00:43:20 +00:00
|
|
|
|
size -= len;
|
|
|
|
|
|
1998-12-10 05:43:07 +00:00
|
|
|
|
while (p != NULL && *p)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
{
|
|
|
|
|
q = p;
|
|
|
|
|
p = strchr (q, '\\');
|
|
|
|
|
if (p) *p = '\0';
|
|
|
|
|
len = get_long_basename (full, o, size);
|
|
|
|
|
if (len > 0)
|
|
|
|
|
{
|
|
|
|
|
o += len;
|
|
|
|
|
size -= len;
|
|
|
|
|
if (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
*p++ = '\\';
|
|
|
|
|
if (size < 2)
|
|
|
|
|
return FALSE;
|
|
|
|
|
*o++ = '\\';
|
|
|
|
|
size--;
|
|
|
|
|
*o = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
1998-06-17 04:22:58 +00:00
|
|
|
|
int
|
|
|
|
|
is_unc_volume (const char *filename)
|
|
|
|
|
{
|
|
|
|
|
const char *ptr = filename;
|
|
|
|
|
|
|
|
|
|
if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
|
|
|
|
|
return 0;
|
|
|
|
|
|
2007-02-23 18:40:41 +00:00
|
|
|
|
if (_mbspbrk (ptr + 2, "*?|<>\"\\/"))
|
1998-06-17 04:22:58 +00:00
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
1994-11-01 10:27:02 +00:00
|
|
|
|
/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
sigsetmask (int signal_mask)
|
|
|
|
|
{
|
1994-11-01 10:27:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
sigmask (int sig)
|
|
|
|
|
{
|
2000-02-06 23:37:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
sigblock (int sig)
|
|
|
|
|
{
|
1994-11-01 10:27:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
sigunblock (int sig)
|
|
|
|
|
{
|
2000-02-06 23:37:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
setpgrp (int pid, int gid)
|
|
|
|
|
{
|
1994-11-01 10:27:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
int
|
|
|
|
|
alarm (int seconds)
|
|
|
|
|
{
|
1994-11-01 10:27:02 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
|
1995-11-07 07:36:09 +00:00
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
LPBYTE
|
1996-11-19 04:59:23 +00:00
|
|
|
|
w32_get_resource (key, lpdwtype)
|
1995-11-07 07:36:09 +00:00
|
|
|
|
char *key;
|
|
|
|
|
LPDWORD lpdwtype;
|
|
|
|
|
{
|
|
|
|
|
LPBYTE lpvalue;
|
|
|
|
|
HKEY hrootkey = NULL;
|
|
|
|
|
DWORD cbData;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
|
|
|
|
/* Check both the current user and the local machine to see if
|
1995-11-07 07:36:09 +00:00
|
|
|
|
we have any resources. */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
lpvalue = NULL;
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
|
|
|
|
|
&& (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
|
1995-11-07 07:36:09 +00:00
|
|
|
|
&& RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
|
|
|
|
|
{
|
2007-09-29 21:33:23 +00:00
|
|
|
|
RegCloseKey (hrootkey);
|
1995-11-07 07:36:09 +00:00
|
|
|
|
return (lpvalue);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-02 06:09:17 +00:00
|
|
|
|
xfree (lpvalue);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
RegCloseKey (hrootkey);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
lpvalue = NULL;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
|
|
|
|
|
&& (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
|
|
|
|
|
&& RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
|
1995-11-07 07:36:09 +00:00
|
|
|
|
{
|
2007-09-29 21:33:23 +00:00
|
|
|
|
RegCloseKey (hrootkey);
|
1995-11-07 07:36:09 +00:00
|
|
|
|
return (lpvalue);
|
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
2008-06-02 06:09:17 +00:00
|
|
|
|
xfree (lpvalue);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
RegCloseKey (hrootkey);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-20 01:52:48 +00:00
|
|
|
|
char *get_emacs_configuration (void);
|
|
|
|
|
extern Lisp_Object Vsystem_configuration;
|
|
|
|
|
|
1995-11-07 07:36:09 +00:00
|
|
|
|
void
|
1999-01-30 18:48:57 +00:00
|
|
|
|
init_environment (char ** argv)
|
1995-11-07 07:36:09 +00:00
|
|
|
|
{
|
1998-06-05 16:08:32 +00:00
|
|
|
|
static const char * const tempdirs[] = {
|
|
|
|
|
"$TMPDIR", "$TEMP", "$TMP", "c:/"
|
|
|
|
|
};
|
2005-07-14 22:32:50 +00:00
|
|
|
|
|
1998-06-05 16:08:32 +00:00
|
|
|
|
int i;
|
2005-07-14 22:32:50 +00:00
|
|
|
|
|
1998-06-05 16:08:32 +00:00
|
|
|
|
const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
|
|
|
|
|
|
|
|
|
|
/* Make sure they have a usable $TMPDIR. Many Emacs functions use
|
|
|
|
|
temporary files and assume "/tmp" if $TMPDIR is unset, which
|
|
|
|
|
will break on DOS/Windows. Refuse to work if we cannot find
|
|
|
|
|
a directory, not even "c:/", usable for that purpose. */
|
|
|
|
|
for (i = 0; i < imax ; i++)
|
|
|
|
|
{
|
|
|
|
|
const char *tmp = tempdirs[i];
|
|
|
|
|
|
|
|
|
|
if (*tmp == '$')
|
|
|
|
|
tmp = getenv (tmp + 1);
|
|
|
|
|
/* Note that `access' can lie to us if the directory resides on a
|
|
|
|
|
read-only filesystem, like CD-ROM or a write-protected floppy.
|
|
|
|
|
The only way to be really sure is to actually create a file and
|
|
|
|
|
see if it succeeds. But I think that's too much to ask. */
|
2000-08-22 22:49:27 +00:00
|
|
|
|
if (tmp && _access (tmp, D_OK) == 0)
|
1998-06-05 16:08:32 +00:00
|
|
|
|
{
|
|
|
|
|
char * var = alloca (strlen (tmp) + 8);
|
|
|
|
|
sprintf (var, "TMPDIR=%s", tmp);
|
2001-02-09 09:57:04 +00:00
|
|
|
|
_putenv (strdup (var));
|
1998-06-05 16:08:32 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (i >= imax)
|
|
|
|
|
cmd_error_internal
|
|
|
|
|
(Fcons (Qerror,
|
|
|
|
|
Fcons (build_string ("no usable temporary directories found!!"),
|
|
|
|
|
Qnil)),
|
|
|
|
|
"While setting TMPDIR: ");
|
|
|
|
|
|
2000-07-05 16:00:13 +00:00
|
|
|
|
/* Check for environment variables and use registry settings if they
|
|
|
|
|
don't exist. Fallback on default values where applicable. */
|
1995-11-07 07:36:09 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int i;
|
|
|
|
|
LPBYTE lpval;
|
|
|
|
|
DWORD dwType;
|
2000-11-24 21:30:06 +00:00
|
|
|
|
char locale_name[32];
|
2005-07-14 22:32:50 +00:00
|
|
|
|
struct stat ignored;
|
|
|
|
|
char default_home[MAX_PATH];
|
1995-11-07 07:36:09 +00:00
|
|
|
|
|
2006-05-19 19:05:07 +00:00
|
|
|
|
static const struct env_entry
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
|
|
|
|
char * name;
|
|
|
|
|
char * def_value;
|
2006-05-19 19:05:07 +00:00
|
|
|
|
} dflt_envvars[] =
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
|
|
|
|
{"HOME", "C:/"},
|
|
|
|
|
{"PRELOAD_WINSOCK", NULL},
|
|
|
|
|
{"emacs_dir", "C:/emacs"},
|
2001-01-19 14:56:06 +00:00
|
|
|
|
{"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
|
|
|
|
|
{"EMACSDATA", "%emacs_dir%/etc"},
|
|
|
|
|
{"EMACSPATH", "%emacs_dir%/bin"},
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* We no longer set INFOPATH because Info-default-directory-list
|
2000-07-05 16:00:13 +00:00
|
|
|
|
is then ignored. */
|
|
|
|
|
/* {"INFOPATH", "%emacs_dir%/info"}, */
|
|
|
|
|
{"EMACSDOC", "%emacs_dir%/etc"},
|
2000-11-24 21:30:06 +00:00
|
|
|
|
{"TERM", "cmd"},
|
|
|
|
|
{"LANG", NULL},
|
1996-05-03 18:32:52 +00:00
|
|
|
|
};
|
|
|
|
|
|
2006-05-19 19:05:07 +00:00
|
|
|
|
#define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
|
|
|
|
|
|
|
|
|
|
/* We need to copy dflt_envvars[] and work on the copy because we
|
|
|
|
|
don't want the dumped Emacs to inherit the values of
|
|
|
|
|
environment variables we saw during dumping (which could be on
|
|
|
|
|
a different system). The defaults above must be left intact. */
|
|
|
|
|
struct env_entry env_vars[N_ENV_VARS];
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < N_ENV_VARS; i++)
|
|
|
|
|
env_vars[i] = dflt_envvars[i];
|
|
|
|
|
|
2005-07-14 22:32:50 +00:00
|
|
|
|
/* For backwards compatibility, check if a .emacs file exists in C:/
|
|
|
|
|
If not, then we can try to default to the appdata directory under the
|
|
|
|
|
user's profile, which is more likely to be writable. */
|
|
|
|
|
if (stat ("C:/.emacs", &ignored) < 0)
|
|
|
|
|
{
|
|
|
|
|
HRESULT profile_result;
|
|
|
|
|
/* Dynamically load ShGetFolderPath, as it won't exist on versions
|
|
|
|
|
of Windows 95 and NT4 that have not been updated to include
|
2008-12-03 14:13:42 +00:00
|
|
|
|
MSIE 5. */
|
2005-07-14 22:32:50 +00:00
|
|
|
|
ShGetFolderPath_fn get_folder_path;
|
|
|
|
|
get_folder_path = (ShGetFolderPath_fn)
|
2008-12-03 14:13:42 +00:00
|
|
|
|
GetProcAddress (GetModuleHandle ("shell32.dll"), "SHGetFolderPathA");
|
2005-07-14 22:32:50 +00:00
|
|
|
|
|
|
|
|
|
if (get_folder_path != NULL)
|
|
|
|
|
{
|
|
|
|
|
profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
|
|
|
|
|
0, default_home);
|
|
|
|
|
|
2008-06-27 07:34:53 +00:00
|
|
|
|
/* If we can't get the appdata dir, revert to old behavior. */
|
2005-07-14 22:32:50 +00:00
|
|
|
|
if (profile_result == S_OK)
|
|
|
|
|
env_vars[0].def_value = default_home;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-11-24 21:30:06 +00:00
|
|
|
|
/* Get default locale info and use it for LANG. */
|
|
|
|
|
if (GetLocaleInfo (LOCALE_USER_DEFAULT,
|
|
|
|
|
LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
|
|
|
|
|
locale_name, sizeof (locale_name)))
|
|
|
|
|
{
|
2006-05-19 19:05:07 +00:00
|
|
|
|
for (i = 0; i < N_ENV_VARS; i++)
|
2000-11-24 21:30:06 +00:00
|
|
|
|
{
|
|
|
|
|
if (strcmp (env_vars[i].name, "LANG") == 0)
|
|
|
|
|
{
|
|
|
|
|
env_vars[i].def_value = locale_name;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-05 16:00:13 +00:00
|
|
|
|
#define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
|
|
|
|
|
|
|
|
|
|
/* Treat emacs_dir specially: set it unconditionally based on our
|
|
|
|
|
location, if it appears that we are running from the bin subdir
|
|
|
|
|
of a standard installation. */
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
|
|
|
|
char modname[MAX_PATH];
|
|
|
|
|
|
|
|
|
|
if (!GetModuleFileName (NULL, modname, MAX_PATH))
|
|
|
|
|
abort ();
|
|
|
|
|
if ((p = strrchr (modname, '\\')) == NULL)
|
|
|
|
|
abort ();
|
|
|
|
|
*p = 0;
|
|
|
|
|
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
|
|
|
|
char buf[SET_ENV_BUF_SIZE];
|
|
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
|
for (p = modname; *p; p++)
|
|
|
|
|
if (*p == '\\') *p = '/';
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
2000-07-05 16:00:13 +00:00
|
|
|
|
_snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
|
2000-08-22 22:49:27 +00:00
|
|
|
|
_putenv (strdup (buf));
|
2000-07-05 16:00:13 +00:00
|
|
|
|
}
|
2004-10-19 19:09:37 +00:00
|
|
|
|
/* Handle running emacs from the build directory: src/oo-spd/i386/ */
|
|
|
|
|
|
|
|
|
|
/* FIXME: should use substring of get_emacs_configuration ().
|
|
|
|
|
But I don't think the Windows build supports alpha, mips etc
|
|
|
|
|
anymore, so have taken the easy option for now. */
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
else if (p && xstrcasecmp (p, "\\i386") == 0)
|
2004-10-19 19:09:37 +00:00
|
|
|
|
{
|
|
|
|
|
*p = 0;
|
|
|
|
|
p = strrchr (modname, '\\');
|
|
|
|
|
if (p != NULL)
|
|
|
|
|
{
|
|
|
|
|
*p = 0;
|
|
|
|
|
p = strrchr (modname, '\\');
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if (p && xstrcasecmp (p, "\\src") == 0)
|
2004-10-19 19:09:37 +00:00
|
|
|
|
{
|
|
|
|
|
char buf[SET_ENV_BUF_SIZE];
|
|
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
|
for (p = modname; *p; p++)
|
|
|
|
|
if (*p == '\\') *p = '/';
|
|
|
|
|
|
|
|
|
|
_snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
|
|
|
|
|
_putenv (strdup (buf));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2000-07-05 16:00:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-05-19 19:05:07 +00:00
|
|
|
|
for (i = 0; i < N_ENV_VARS; i++)
|
1995-11-07 07:36:09 +00:00
|
|
|
|
{
|
2000-07-05 16:00:13 +00:00
|
|
|
|
if (!getenv (env_vars[i].name))
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2000-07-05 16:00:13 +00:00
|
|
|
|
int dont_free = 0;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2007-06-20 08:31:09 +00:00
|
|
|
|
if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL
|
|
|
|
|
/* Also ignore empty environment variables. */
|
|
|
|
|
|| *lpval == 0)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
2008-06-02 06:09:17 +00:00
|
|
|
|
xfree (lpval);
|
2000-07-05 16:00:13 +00:00
|
|
|
|
lpval = env_vars[i].def_value;
|
|
|
|
|
dwType = REG_EXPAND_SZ;
|
|
|
|
|
dont_free = 1;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
2000-07-05 16:00:13 +00:00
|
|
|
|
|
|
|
|
|
if (lpval)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2006-05-19 19:29:36 +00:00
|
|
|
|
char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
|
2000-07-05 16:00:13 +00:00
|
|
|
|
|
2006-05-19 19:29:36 +00:00
|
|
|
|
if (dwType == REG_EXPAND_SZ)
|
|
|
|
|
ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
|
2000-07-05 16:00:13 +00:00
|
|
|
|
else if (dwType == REG_SZ)
|
2006-05-19 19:29:36 +00:00
|
|
|
|
strcpy (buf1, lpval);
|
|
|
|
|
if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
2006-05-19 19:29:36 +00:00
|
|
|
|
_snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
|
|
|
|
|
buf1);
|
|
|
|
|
_putenv (strdup (buf2));
|
2000-07-05 16:00:13 +00:00
|
|
|
|
}
|
1995-11-07 07:36:09 +00:00
|
|
|
|
|
2000-07-05 16:00:13 +00:00
|
|
|
|
if (!dont_free)
|
|
|
|
|
xfree (lpval);
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-20 01:52:48 +00:00
|
|
|
|
/* Rebuild system configuration to reflect invoking system. */
|
|
|
|
|
Vsystem_configuration = build_string (EMACS_CONFIGURATION);
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Another special case: on NT, the PATH variable is actually named
|
|
|
|
|
"Path" although cmd.exe (perhaps NT itself) arranges for
|
|
|
|
|
environment variable lookup and setting to be case insensitive.
|
|
|
|
|
However, Emacs assumes a fully case sensitive environment, so we
|
|
|
|
|
need to change "Path" to "PATH" to match the expectations of
|
|
|
|
|
various elisp packages. We do this by the sneaky method of
|
|
|
|
|
modifying the string in the C runtime environ entry.
|
|
|
|
|
|
|
|
|
|
The same applies to COMSPEC. */
|
|
|
|
|
{
|
|
|
|
|
char ** envp;
|
|
|
|
|
|
|
|
|
|
for (envp = environ; *envp; envp++)
|
|
|
|
|
if (_strnicmp (*envp, "PATH=", 5) == 0)
|
|
|
|
|
memcpy (*envp, "PATH=", 5);
|
|
|
|
|
else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
|
|
|
|
|
memcpy (*envp, "COMSPEC=", 8);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remember the initial working directory for getwd, then make the
|
|
|
|
|
real wd be the location of emacs.exe to avoid conflicts when
|
|
|
|
|
renaming or deleting directories. (We also don't call chdir when
|
|
|
|
|
running subprocesses for the same reason.) */
|
|
|
|
|
if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
char *p;
|
1999-01-30 18:48:57 +00:00
|
|
|
|
static char modname[MAX_PATH];
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
|
|
|
|
if (!GetModuleFileName (NULL, modname, MAX_PATH))
|
|
|
|
|
abort ();
|
|
|
|
|
if ((p = strrchr (modname, '\\')) == NULL)
|
|
|
|
|
abort ();
|
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
|
|
SetCurrentDirectory (modname);
|
1999-01-30 18:48:57 +00:00
|
|
|
|
|
|
|
|
|
/* Ensure argv[0] has the full path to Emacs. */
|
|
|
|
|
*p = '\\';
|
|
|
|
|
argv[0] = modname;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-27 21:28:38 +00:00
|
|
|
|
/* Determine if there is a middle mouse button, to allow parse_button
|
|
|
|
|
to decide whether right mouse events should be mouse-2 or
|
|
|
|
|
mouse-3. */
|
2004-05-17 21:33:16 +00:00
|
|
|
|
w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
|
2000-02-27 21:28:38 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
init_user_info ();
|
|
|
|
|
}
|
|
|
|
|
|
2001-12-19 19:00:44 +00:00
|
|
|
|
char *
|
|
|
|
|
emacs_root_dir (void)
|
|
|
|
|
{
|
|
|
|
|
static char root_dir[FILENAME_MAX];
|
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
|
|
p = getenv ("emacs_dir");
|
|
|
|
|
if (p == NULL)
|
|
|
|
|
abort ();
|
|
|
|
|
strcpy (root_dir, p);
|
|
|
|
|
root_dir[parse_root (root_dir, NULL)] = '\0';
|
|
|
|
|
dostounix_filename (root_dir);
|
|
|
|
|
return root_dir;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* We don't have scripts to automatically determine the system configuration
|
|
|
|
|
for Emacs before it's compiled, and we don't want to have to make the
|
|
|
|
|
user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
|
|
|
|
|
routine. */
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
get_emacs_configuration (void)
|
|
|
|
|
{
|
|
|
|
|
char *arch, *oem, *os;
|
1999-06-24 22:05:14 +00:00
|
|
|
|
int build_num;
|
2000-08-22 22:49:27 +00:00
|
|
|
|
static char configuration_buffer[32];
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* Determine the processor type. */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
switch (get_processor_type ())
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
#ifdef PROCESSOR_INTEL_386
|
|
|
|
|
case PROCESSOR_INTEL_386:
|
|
|
|
|
case PROCESSOR_INTEL_486:
|
|
|
|
|
case PROCESSOR_INTEL_PENTIUM:
|
|
|
|
|
arch = "i386";
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef PROCESSOR_MIPS_R2000
|
|
|
|
|
case PROCESSOR_MIPS_R2000:
|
|
|
|
|
case PROCESSOR_MIPS_R3000:
|
|
|
|
|
case PROCESSOR_MIPS_R4000:
|
|
|
|
|
arch = "mips";
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef PROCESSOR_ALPHA_21064
|
|
|
|
|
case PROCESSOR_ALPHA_21064:
|
|
|
|
|
arch = "alpha";
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
arch = "unknown";
|
|
|
|
|
break;
|
1995-11-07 07:36:09 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2000-08-22 22:49:27 +00:00
|
|
|
|
/* Use the OEM field to reflect the compiler/library combination. */
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#define COMPILER_NAME "msvc"
|
|
|
|
|
#else
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
#define COMPILER_NAME "mingw"
|
|
|
|
|
#else
|
|
|
|
|
#define COMPILER_NAME "unknown"
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
oem = COMPILER_NAME;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1999-06-24 22:05:14 +00:00
|
|
|
|
switch (osinfo_cache.dwPlatformId) {
|
|
|
|
|
case VER_PLATFORM_WIN32_NT:
|
|
|
|
|
os = "nt";
|
|
|
|
|
build_num = osinfo_cache.dwBuildNumber;
|
|
|
|
|
break;
|
|
|
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
|
|
|
if (osinfo_cache.dwMinorVersion == 0) {
|
|
|
|
|
os = "windows95";
|
|
|
|
|
} else {
|
|
|
|
|
os = "windows98";
|
|
|
|
|
}
|
|
|
|
|
build_num = LOWORD (osinfo_cache.dwBuildNumber);
|
|
|
|
|
break;
|
|
|
|
|
case VER_PLATFORM_WIN32s:
|
|
|
|
|
/* Not supported, should not happen. */
|
|
|
|
|
os = "windows32s";
|
|
|
|
|
build_num = LOWORD (osinfo_cache.dwBuildNumber);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
os = "unknown";
|
|
|
|
|
build_num = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
|
|
|
sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
|
|
|
|
|
get_w32_major_version (), get_w32_minor_version (), build_num);
|
|
|
|
|
} else {
|
|
|
|
|
sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
return configuration_buffer;
|
1995-11-07 07:36:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-22 22:49:27 +00:00
|
|
|
|
char *
|
|
|
|
|
get_emacs_configuration_options (void)
|
|
|
|
|
{
|
|
|
|
|
static char options_buffer[256];
|
|
|
|
|
|
|
|
|
|
/* Work out the effective configure options for this build. */
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
|
|
|
|
|
#else
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
#define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
|
|
|
|
|
#else
|
|
|
|
|
#define COMPILER_VERSION ""
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
sprintf (options_buffer, COMPILER_VERSION);
|
|
|
|
|
#ifdef EMACSDEBUG
|
|
|
|
|
strcat (options_buffer, " --no-opt");
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef USER_CFLAGS
|
|
|
|
|
strcat (options_buffer, " --cflags");
|
|
|
|
|
strcat (options_buffer, USER_CFLAGS);
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef USER_LDFLAGS
|
|
|
|
|
strcat (options_buffer, " --ldflags");
|
|
|
|
|
strcat (options_buffer, USER_LDFLAGS);
|
|
|
|
|
#endif
|
|
|
|
|
return options_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1995-04-12 02:10:10 +00:00
|
|
|
|
#include <sys/timeb.h>
|
|
|
|
|
|
|
|
|
|
/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
void
|
1995-04-12 02:10:10 +00:00
|
|
|
|
gettimeofday (struct timeval *tv, struct timezone *tz)
|
|
|
|
|
{
|
2005-06-04 20:39:15 +00:00
|
|
|
|
struct _timeb tb;
|
1995-04-12 02:10:10 +00:00
|
|
|
|
_ftime (&tb);
|
|
|
|
|
|
|
|
|
|
tv->tv_sec = tb.time;
|
|
|
|
|
tv->tv_usec = tb.millitm * 1000L;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
if (tz)
|
1995-04-12 02:10:10 +00:00
|
|
|
|
{
|
|
|
|
|
tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
|
|
|
|
|
tz->tz_dsttime = tb.dstflag; /* type of dst correction */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* ------------------------------------------------------------------------- */
|
1996-11-19 04:59:23 +00:00
|
|
|
|
/* IO support and wrapper functions for W32 API. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* ------------------------------------------------------------------------- */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Place a wrapper around the MSVC version of ctime. It returns NULL
|
2003-02-04 14:56:31 +00:00
|
|
|
|
on network directories, so we handle that case here.
|
1996-05-03 18:32:52 +00:00
|
|
|
|
(Ulrich Leodolter, 1/11/95). */
|
|
|
|
|
char *
|
|
|
|
|
sys_ctime (const time_t *t)
|
|
|
|
|
{
|
|
|
|
|
char *str = (char *) ctime (t);
|
|
|
|
|
return (str ? str : "Sun Jan 01 00:00:00 1970");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Emulate sleep...we could have done this with a define, but that
|
|
|
|
|
would necessitate including windows.h in the files that used it.
|
|
|
|
|
This is much easier. */
|
|
|
|
|
void
|
|
|
|
|
sys_sleep (int seconds)
|
|
|
|
|
{
|
|
|
|
|
Sleep (seconds * 1000);
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Internal MSVC functions for low-level descriptor munging */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
extern int __cdecl _set_osfhnd (int fd, long h);
|
|
|
|
|
extern int __cdecl _free_osfhnd (int fd);
|
|
|
|
|
|
|
|
|
|
/* parallel array of private info on file handles */
|
|
|
|
|
filedesc fd_info [ MAXDESC ];
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
typedef struct volume_info_data {
|
|
|
|
|
struct volume_info_data * next;
|
|
|
|
|
|
|
|
|
|
/* time when info was obtained */
|
|
|
|
|
DWORD timestamp;
|
|
|
|
|
|
|
|
|
|
/* actual volume info */
|
|
|
|
|
char * root_dir;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
DWORD serialnum;
|
|
|
|
|
DWORD maxcomp;
|
|
|
|
|
DWORD flags;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
char * name;
|
|
|
|
|
char * type;
|
|
|
|
|
} volume_info_data;
|
|
|
|
|
|
|
|
|
|
/* Global referenced by various functions. */
|
|
|
|
|
static volume_info_data volume_info;
|
|
|
|
|
|
|
|
|
|
/* Vector to indicate which drives are local and fixed (for which cached
|
|
|
|
|
data never expires). */
|
|
|
|
|
static BOOL fixed_drives[26];
|
|
|
|
|
|
|
|
|
|
/* Consider cached volume information to be stale if older than 10s,
|
|
|
|
|
at least for non-local drives. Info for fixed drives is never stale. */
|
|
|
|
|
#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
|
|
|
|
|
#define VOLINFO_STILL_VALID( root_dir, info ) \
|
|
|
|
|
( ( isalpha (root_dir[0]) && \
|
|
|
|
|
fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
|
|
|
|
|
|| GetTickCount () - info->timestamp < 10000 )
|
|
|
|
|
|
|
|
|
|
/* Cache support functions. */
|
|
|
|
|
|
|
|
|
|
/* Simple linked list with linear search is sufficient. */
|
|
|
|
|
static volume_info_data *volume_cache = NULL;
|
|
|
|
|
|
|
|
|
|
static volume_info_data *
|
|
|
|
|
lookup_volume_info (char * root_dir)
|
|
|
|
|
{
|
|
|
|
|
volume_info_data * info;
|
|
|
|
|
|
|
|
|
|
for (info = volume_cache; info; info = info->next)
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
if (xstrcasecmp (info->root_dir, root_dir) == 0)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
break;
|
|
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_volume_info (char * root_dir, volume_info_data * info)
|
|
|
|
|
{
|
2000-08-22 22:49:27 +00:00
|
|
|
|
info->root_dir = xstrdup (root_dir);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
info->next = volume_cache;
|
|
|
|
|
volume_cache = info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Wrapper for GetVolumeInformation, which uses caching to avoid
|
|
|
|
|
performance penalty (~2ms on 486 for local drives, 7.5ms for local
|
|
|
|
|
cdrom drive, ~5-10ms or more for remote drives on LAN). */
|
|
|
|
|
volume_info_data *
|
|
|
|
|
GetCachedVolumeInformation (char * root_dir)
|
|
|
|
|
{
|
|
|
|
|
volume_info_data * info;
|
|
|
|
|
char default_root[ MAX_PATH ];
|
|
|
|
|
|
|
|
|
|
/* NULL for root_dir means use root from current directory. */
|
|
|
|
|
if (root_dir == NULL)
|
|
|
|
|
{
|
|
|
|
|
if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
parse_root (default_root, &root_dir);
|
|
|
|
|
*root_dir = 0;
|
|
|
|
|
root_dir = default_root;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Local fixed drives can be cached permanently. Removable drives
|
|
|
|
|
cannot be cached permanently, since the volume name and serial
|
|
|
|
|
number (if nothing else) can change. Remote drives should be
|
|
|
|
|
treated as if they are removable, since there is no sure way to
|
|
|
|
|
tell whether they are or not. Also, the UNC association of drive
|
|
|
|
|
letters mapped to remote volumes can be changed at any time (even
|
|
|
|
|
by other processes) without notice.
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
As a compromise, so we can benefit from caching info for remote
|
|
|
|
|
volumes, we use a simple expiry mechanism to invalidate cache
|
|
|
|
|
entries that are more than ten seconds old. */
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* No point doing this, because WNetGetConnection is even slower than
|
|
|
|
|
GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
|
|
|
|
|
GetDriveType is about the only call of this type which does not
|
|
|
|
|
involve network access, and so is extremely quick). */
|
|
|
|
|
|
|
|
|
|
/* Map drive letter to UNC if remote. */
|
|
|
|
|
if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
|
|
|
|
|
{
|
|
|
|
|
char remote_name[ 256 ];
|
|
|
|
|
char drive[3] = { root_dir[0], ':' };
|
|
|
|
|
|
|
|
|
|
if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
|
|
|
|
|
== NO_ERROR)
|
|
|
|
|
/* do something */ ;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
info = lookup_volume_info (root_dir);
|
|
|
|
|
|
|
|
|
|
if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
|
|
|
|
|
{
|
|
|
|
|
char name[ 256 ];
|
|
|
|
|
DWORD serialnum;
|
|
|
|
|
DWORD maxcomp;
|
|
|
|
|
DWORD flags;
|
|
|
|
|
char type[ 256 ];
|
|
|
|
|
|
|
|
|
|
/* Info is not cached, or is stale. */
|
|
|
|
|
if (!GetVolumeInformation (root_dir,
|
|
|
|
|
name, sizeof (name),
|
|
|
|
|
&serialnum,
|
|
|
|
|
&maxcomp,
|
|
|
|
|
&flags,
|
|
|
|
|
type, sizeof (type)))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Cache the volume information for future use, overwriting existing
|
|
|
|
|
entry if present. */
|
|
|
|
|
if (info == NULL)
|
|
|
|
|
{
|
|
|
|
|
info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
|
|
|
|
|
add_volume_info (root_dir, info);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2000-08-22 22:49:27 +00:00
|
|
|
|
xfree (info->name);
|
|
|
|
|
xfree (info->type);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-08-22 22:49:27 +00:00
|
|
|
|
info->name = xstrdup (name);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
info->serialnum = serialnum;
|
|
|
|
|
info->maxcomp = maxcomp;
|
|
|
|
|
info->flags = flags;
|
2000-08-22 22:49:27 +00:00
|
|
|
|
info->type = xstrdup (type);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
info->timestamp = GetTickCount ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* Get information on the volume where name is held; set path pointer to
|
|
|
|
|
start of pathname in name (past UNC header\volume header if present). */
|
|
|
|
|
int
|
|
|
|
|
get_volume_info (const char * name, const char ** pPath)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
char temp[MAX_PATH];
|
|
|
|
|
char *rootname = NULL; /* default to current volume */
|
1997-09-03 00:43:20 +00:00
|
|
|
|
volume_info_data * info;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (name == NULL)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* find the root name of the volume if given */
|
|
|
|
|
if (isalpha (name[0]) && name[1] == ':')
|
|
|
|
|
{
|
|
|
|
|
rootname = temp;
|
|
|
|
|
temp[0] = *name++;
|
|
|
|
|
temp[1] = *name++;
|
|
|
|
|
temp[2] = '\\';
|
|
|
|
|
temp[3] = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
char *str = temp;
|
|
|
|
|
int slashes = 4;
|
|
|
|
|
rootname = temp;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
|
|
|
|
|
break;
|
|
|
|
|
*str++ = *name++;
|
|
|
|
|
}
|
|
|
|
|
while ( *name );
|
|
|
|
|
|
|
|
|
|
*str++ = '\\';
|
|
|
|
|
*str = 0;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (pPath)
|
|
|
|
|
*pPath = name;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
info = GetCachedVolumeInformation (rootname);
|
|
|
|
|
if (info != NULL)
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Set global referenced by other functions. */
|
|
|
|
|
volume_info = *info;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return TRUE;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Determine if volume is FAT format (ie. only supports short 8.3
|
|
|
|
|
names); also set path pointer to start of pathname in name. */
|
|
|
|
|
int
|
|
|
|
|
is_fat_volume (const char * name, const char ** pPath)
|
|
|
|
|
{
|
|
|
|
|
if (get_volume_info (name, pPath))
|
|
|
|
|
return (volume_info.maxcomp == 12);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-05 02:30:41 +00:00
|
|
|
|
/* Map filename to a valid 8.3 name if necessary. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
const char *
|
1996-11-19 04:59:23 +00:00
|
|
|
|
map_w32_filename (const char * name, const char ** pPath)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
static char shortname[MAX_PATH];
|
|
|
|
|
char * str = shortname;
|
|
|
|
|
char c;
|
|
|
|
|
char * path;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
const char * save_name = name;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2000-07-05 16:00:13 +00:00
|
|
|
|
if (strlen (name) >= MAX_PATH)
|
|
|
|
|
{
|
|
|
|
|
/* Return a filename which will cause callers to fail. */
|
|
|
|
|
strcpy (shortname, "?");
|
|
|
|
|
return shortname;
|
|
|
|
|
}
|
|
|
|
|
|
2000-08-22 22:49:27 +00:00
|
|
|
|
if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
|
1994-11-01 10:27:02 +00:00
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
register int left = 8; /* maximum number of chars in part */
|
|
|
|
|
register int extn = 0; /* extension added? */
|
|
|
|
|
register int dots = 2; /* maximum number of dots allowed */
|
|
|
|
|
|
|
|
|
|
while (name < path)
|
|
|
|
|
*str++ = *name++; /* skip past UNC header */
|
|
|
|
|
|
|
|
|
|
while ((c = *name++))
|
|
|
|
|
{
|
|
|
|
|
switch ( c )
|
|
|
|
|
{
|
|
|
|
|
case '\\':
|
|
|
|
|
case '/':
|
|
|
|
|
*str++ = '\\';
|
|
|
|
|
extn = 0; /* reset extension flags */
|
|
|
|
|
dots = 2; /* max 2 dots */
|
|
|
|
|
left = 8; /* max length 8 for main part */
|
|
|
|
|
break;
|
|
|
|
|
case ':':
|
|
|
|
|
*str++ = ':';
|
|
|
|
|
extn = 0; /* reset extension flags */
|
|
|
|
|
dots = 2; /* max 2 dots */
|
|
|
|
|
left = 8; /* max length 8 for main part */
|
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
if ( dots )
|
|
|
|
|
{
|
|
|
|
|
/* Convert path components of the form .xxx to _xxx,
|
|
|
|
|
but leave . and .. as they are. This allows .emacs
|
|
|
|
|
to be read as _emacs, for example. */
|
|
|
|
|
|
|
|
|
|
if (! *name ||
|
|
|
|
|
*name == '.' ||
|
|
|
|
|
IS_DIRECTORY_SEP (*name))
|
|
|
|
|
{
|
|
|
|
|
*str++ = '.';
|
|
|
|
|
dots--;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*str++ = '_';
|
|
|
|
|
left--;
|
|
|
|
|
dots = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ( !extn )
|
|
|
|
|
{
|
|
|
|
|
*str++ = '.';
|
|
|
|
|
extn = 1; /* we've got an extension */
|
|
|
|
|
left = 3; /* 3 chars in extension */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* any embedded dots after the first are converted to _ */
|
|
|
|
|
*str++ = '_';
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '~':
|
|
|
|
|
case '#': /* don't lose these, they're important */
|
|
|
|
|
if ( ! left )
|
|
|
|
|
str[-1] = c; /* replace last character of part */
|
|
|
|
|
/* FALLTHRU */
|
|
|
|
|
default:
|
|
|
|
|
if ( left )
|
|
|
|
|
{
|
|
|
|
|
*str++ = tolower (c); /* map to lower case (looks nicer) */
|
|
|
|
|
left--;
|
|
|
|
|
dots = 0; /* started a path component */
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*str = '\0';
|
1996-05-11 17:26:00 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy (shortname, name);
|
|
|
|
|
unixtodos_filename (shortname);
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (pPath)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
*pPath = shortname + (path - save_name);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1996-05-11 17:26:00 +00:00
|
|
|
|
return shortname;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1998-06-05 16:08:32 +00:00
|
|
|
|
static int
|
|
|
|
|
is_exec (const char * name)
|
|
|
|
|
{
|
|
|
|
|
char * p = strrchr (name, '.');
|
|
|
|
|
return
|
|
|
|
|
(p != NULL
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
&& (xstrcasecmp (p, ".exe") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".com") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".bat") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".cmd") == 0));
|
1998-06-05 16:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
/* Emulate the Unix directory procedures opendir, closedir,
|
1997-09-03 00:43:20 +00:00
|
|
|
|
and readdir. We can't use the procedures supplied in sysdep.c,
|
|
|
|
|
so we provide them here. */
|
|
|
|
|
|
|
|
|
|
struct direct dir_static; /* simulated directory contents */
|
|
|
|
|
static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
|
|
|
|
|
static int dir_is_fat;
|
|
|
|
|
static char dir_pathname[MAXPATHLEN+1];
|
|
|
|
|
static WIN32_FIND_DATA dir_find_data;
|
|
|
|
|
|
1998-06-17 04:22:58 +00:00
|
|
|
|
/* Support shares on a network resource as subdirectories of a read-only
|
|
|
|
|
root directory. */
|
|
|
|
|
static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
|
2004-05-17 21:33:16 +00:00
|
|
|
|
HANDLE open_unc_volume (const char *);
|
1998-06-17 04:22:58 +00:00
|
|
|
|
char *read_unc_volume (HANDLE, char *, int);
|
|
|
|
|
void close_unc_volume (HANDLE);
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
DIR *
|
|
|
|
|
opendir (char *filename)
|
|
|
|
|
{
|
|
|
|
|
DIR *dirp;
|
|
|
|
|
|
|
|
|
|
/* Opening is done by FindFirstFile. However, a read is inherent to
|
|
|
|
|
this operation, so we defer the open until read time. */
|
|
|
|
|
|
|
|
|
|
if (dir_find_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
return NULL;
|
1998-06-17 04:22:58 +00:00
|
|
|
|
if (wnet_enum_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (is_unc_volume (filename))
|
|
|
|
|
{
|
|
|
|
|
wnet_enum_handle = open_unc_volume (filename);
|
|
|
|
|
if (wnet_enum_handle == INVALID_HANDLE_VALUE)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!(dirp = (DIR *) malloc (sizeof (DIR))))
|
|
|
|
|
return NULL;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
|
|
|
|
dirp->dd_fd = 0;
|
|
|
|
|
dirp->dd_loc = 0;
|
|
|
|
|
dirp->dd_size = 0;
|
|
|
|
|
|
|
|
|
|
strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
|
|
|
|
|
dir_pathname[MAXPATHLEN] = '\0';
|
|
|
|
|
dir_is_fat = is_fat_volume (filename, NULL);
|
|
|
|
|
|
|
|
|
|
return dirp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
closedir (DIR *dirp)
|
|
|
|
|
{
|
|
|
|
|
/* If we have a find-handle open, close it. */
|
|
|
|
|
if (dir_find_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
FindClose (dir_find_handle);
|
|
|
|
|
dir_find_handle = INVALID_HANDLE_VALUE;
|
|
|
|
|
}
|
1998-06-17 04:22:58 +00:00
|
|
|
|
else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
close_unc_volume (wnet_enum_handle);
|
|
|
|
|
wnet_enum_handle = INVALID_HANDLE_VALUE;
|
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
xfree ((char *) dirp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct direct *
|
|
|
|
|
readdir (DIR *dirp)
|
|
|
|
|
{
|
2008-03-22 11:53:40 +00:00
|
|
|
|
int downcase = !NILP (Vw32_downcase_file_names);
|
|
|
|
|
|
1998-06-17 04:22:58 +00:00
|
|
|
|
if (wnet_enum_handle != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
2003-02-04 14:56:31 +00:00
|
|
|
|
if (!read_unc_volume (wnet_enum_handle,
|
|
|
|
|
dir_find_data.cFileName,
|
1998-06-17 04:22:58 +00:00
|
|
|
|
MAX_PATH))
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
|
1998-06-17 04:22:58 +00:00
|
|
|
|
else if (dir_find_handle == INVALID_HANDLE_VALUE)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
{
|
|
|
|
|
char filename[MAXNAMLEN + 3];
|
|
|
|
|
int ln;
|
|
|
|
|
|
|
|
|
|
strcpy (filename, dir_pathname);
|
|
|
|
|
ln = strlen (filename) - 1;
|
|
|
|
|
if (!IS_DIRECTORY_SEP (filename[ln]))
|
|
|
|
|
strcat (filename, "\\");
|
|
|
|
|
strcat (filename, "*");
|
|
|
|
|
|
|
|
|
|
dir_find_handle = FindFirstFile (filename, &dir_find_data);
|
|
|
|
|
|
|
|
|
|
if (dir_find_handle == INVALID_HANDLE_VALUE)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!FindNextFile (dir_find_handle, &dir_find_data))
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Emacs never uses this value, so don't bother making it match
|
|
|
|
|
value returned by stat(). */
|
|
|
|
|
dir_static.d_ino = 1;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
2008-03-22 11:53:40 +00:00
|
|
|
|
strcpy (dir_static.d_name, dir_find_data.cFileName);
|
|
|
|
|
|
|
|
|
|
/* If the file name in cFileName[] includes `?' characters, it means
|
|
|
|
|
the original file name used characters that cannot be represented
|
|
|
|
|
by the current ANSI codepage. To avoid total lossage, retrieve
|
|
|
|
|
the short 8+3 alias of the long file name. */
|
|
|
|
|
if (_mbspbrk (dir_static.d_name, "?"))
|
|
|
|
|
{
|
|
|
|
|
strcpy (dir_static.d_name, dir_find_data.cAlternateFileName);
|
|
|
|
|
downcase = 1; /* 8+3 aliases are returned in all caps */
|
|
|
|
|
}
|
|
|
|
|
dir_static.d_namlen = strlen (dir_static.d_name);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
|
|
|
|
|
dir_static.d_namlen - dir_static.d_namlen % 4;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
2008-03-26 19:06:04 +00:00
|
|
|
|
/* If the file name in cFileName[] includes `?' characters, it means
|
|
|
|
|
the original file name used characters that cannot be represented
|
|
|
|
|
by the current ANSI codepage. To avoid total lossage, retrieve
|
|
|
|
|
the short 8+3 alias of the long file name. */
|
|
|
|
|
if (_mbspbrk (dir_find_data.cFileName, "?"))
|
|
|
|
|
{
|
|
|
|
|
strcpy (dir_static.d_name, dir_find_data.cAlternateFileName);
|
|
|
|
|
/* 8+3 aliases are returned in all caps, which could break
|
|
|
|
|
various alists that look at filenames' extensions. */
|
|
|
|
|
downcase = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
strcpy (dir_static.d_name, dir_find_data.cFileName);
|
|
|
|
|
dir_static.d_namlen = strlen (dir_static.d_name);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
if (dir_is_fat)
|
|
|
|
|
_strlwr (dir_static.d_name);
|
2008-03-22 11:53:40 +00:00
|
|
|
|
else if (downcase)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
{
|
|
|
|
|
register char *p;
|
|
|
|
|
for (p = dir_static.d_name; *p; p++)
|
|
|
|
|
if (*p >= 'a' && *p <= 'z')
|
|
|
|
|
break;
|
|
|
|
|
if (!*p)
|
|
|
|
|
_strlwr (dir_static.d_name);
|
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
return &dir_static;
|
|
|
|
|
}
|
|
|
|
|
|
1998-06-17 04:22:58 +00:00
|
|
|
|
HANDLE
|
2004-05-17 21:33:16 +00:00
|
|
|
|
open_unc_volume (const char *path)
|
1998-06-17 04:22:58 +00:00
|
|
|
|
{
|
2003-02-04 14:56:31 +00:00
|
|
|
|
NETRESOURCE nr;
|
1998-06-17 04:22:58 +00:00
|
|
|
|
HANDLE henum;
|
|
|
|
|
int result;
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
nr.dwScope = RESOURCE_GLOBALNET;
|
|
|
|
|
nr.dwType = RESOURCETYPE_DISK;
|
|
|
|
|
nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
|
|
|
|
|
nr.dwUsage = RESOURCEUSAGE_CONTAINER;
|
|
|
|
|
nr.lpLocalName = NULL;
|
2005-06-04 20:39:15 +00:00
|
|
|
|
nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
nr.lpComment = NULL;
|
|
|
|
|
nr.lpProvider = NULL;
|
1998-06-17 04:22:58 +00:00
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
|
1998-06-17 04:22:58 +00:00
|
|
|
|
RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
|
|
|
|
|
|
|
|
|
|
if (result == NO_ERROR)
|
|
|
|
|
return henum;
|
|
|
|
|
else
|
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
read_unc_volume (HANDLE henum, char *readbuf, int size)
|
|
|
|
|
{
|
2000-08-22 22:49:27 +00:00
|
|
|
|
DWORD count;
|
1998-06-17 04:22:58 +00:00
|
|
|
|
int result;
|
2000-08-22 22:49:27 +00:00
|
|
|
|
DWORD bufsize = 512;
|
1998-06-17 04:22:58 +00:00
|
|
|
|
char *buffer;
|
|
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
|
|
count = 1;
|
|
|
|
|
buffer = alloca (bufsize);
|
|
|
|
|
result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
|
|
|
|
|
if (result != NO_ERROR)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* WNetEnumResource returns \\resource\share...skip forward to "share". */
|
|
|
|
|
ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
|
|
|
|
|
ptr += 2;
|
|
|
|
|
while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
|
|
|
|
|
ptr++;
|
|
|
|
|
|
|
|
|
|
strncpy (readbuf, ptr, size);
|
|
|
|
|
return readbuf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
close_unc_volume (HANDLE henum)
|
|
|
|
|
{
|
|
|
|
|
if (henum != INVALID_HANDLE_VALUE)
|
|
|
|
|
WNetCloseEnum (henum);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
2004-05-17 21:33:16 +00:00
|
|
|
|
unc_volume_file_attributes (const char *path)
|
1998-06-17 04:22:58 +00:00
|
|
|
|
{
|
|
|
|
|
HANDLE henum;
|
|
|
|
|
DWORD attrs;
|
|
|
|
|
|
|
|
|
|
henum = open_unc_volume (path);
|
|
|
|
|
if (henum == INVALID_HANDLE_VALUE)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
|
|
|
|
|
|
close_unc_volume (henum);
|
|
|
|
|
|
|
|
|
|
return attrs;
|
|
|
|
|
}
|
|
|
|
|
|
2008-01-26 01:08:53 +00:00
|
|
|
|
/* Ensure a network connection is authenticated. */
|
|
|
|
|
static void
|
|
|
|
|
logon_network_drive (const char *path)
|
|
|
|
|
{
|
|
|
|
|
NETRESOURCE resource;
|
|
|
|
|
char share[MAX_PATH];
|
|
|
|
|
int i, n_slashes;
|
2008-04-10 11:38:15 +00:00
|
|
|
|
char drive[4];
|
2009-07-11 15:44:36 +00:00
|
|
|
|
UINT drvtype;
|
2008-04-10 11:38:15 +00:00
|
|
|
|
|
2009-07-11 15:44:36 +00:00
|
|
|
|
if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
|
|
|
|
|
drvtype = DRIVE_REMOTE;
|
|
|
|
|
else if (path[0] == '\0' || path[1] != ':')
|
|
|
|
|
drvtype = GetDriveType (NULL);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
drive[0] = path[0];
|
|
|
|
|
drive[1] = ':';
|
|
|
|
|
drive[2] = '\\';
|
|
|
|
|
drive[3] = '\0';
|
|
|
|
|
drvtype = GetDriveType (drive);
|
|
|
|
|
}
|
2008-01-26 01:08:53 +00:00
|
|
|
|
|
|
|
|
|
/* Only logon to networked drives. */
|
2009-07-11 15:44:36 +00:00
|
|
|
|
if (drvtype != DRIVE_REMOTE)
|
2008-01-26 01:08:53 +00:00
|
|
|
|
return;
|
2008-04-10 11:38:15 +00:00
|
|
|
|
|
2008-01-26 01:08:53 +00:00
|
|
|
|
n_slashes = 2;
|
|
|
|
|
strncpy (share, path, MAX_PATH);
|
|
|
|
|
/* Truncate to just server and share name. */
|
|
|
|
|
for (i = 2; i < MAX_PATH; i++)
|
|
|
|
|
{
|
|
|
|
|
if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3)
|
|
|
|
|
{
|
|
|
|
|
share[i] = '\0';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
resource.dwType = RESOURCETYPE_DISK;
|
|
|
|
|
resource.lpLocalName = NULL;
|
|
|
|
|
resource.lpRemoteName = share;
|
|
|
|
|
resource.lpProvider = NULL;
|
|
|
|
|
|
|
|
|
|
WNetAddConnection2 (&resource, NULL, NULL, CONNECT_INTERACTIVE);
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* Shadow some MSVC runtime functions to map requests for long filenames
|
|
|
|
|
to reasonable short names if necessary. This was originally added to
|
2003-02-04 14:56:31 +00:00
|
|
|
|
permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
|
1996-05-03 18:32:52 +00:00
|
|
|
|
long file names. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_access (const char * path, int mode)
|
|
|
|
|
{
|
1998-06-05 16:08:32 +00:00
|
|
|
|
DWORD attributes;
|
|
|
|
|
|
|
|
|
|
/* MSVC implementation doesn't recognize D_OK. */
|
|
|
|
|
path = map_w32_filename (path, NULL);
|
1998-06-17 04:22:58 +00:00
|
|
|
|
if (is_unc_volume (path))
|
|
|
|
|
{
|
|
|
|
|
attributes = unc_volume_file_attributes (path);
|
|
|
|
|
if (attributes == -1) {
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ((attributes = GetFileAttributes (path)) == -1)
|
1998-06-05 16:08:32 +00:00
|
|
|
|
{
|
|
|
|
|
/* Should try mapping GetLastError to errno; for now just indicate
|
|
|
|
|
that path doesn't exist. */
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ((mode & X_OK) != 0 && !is_exec (path))
|
|
|
|
|
{
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
|
|
|
|
|
{
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
|
|
|
|
{
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_chdir (const char * path)
|
|
|
|
|
{
|
1996-11-19 04:59:23 +00:00
|
|
|
|
return _chdir (map_w32_filename (path, NULL));
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_chmod (const char * path, int mode)
|
|
|
|
|
{
|
1996-11-19 04:59:23 +00:00
|
|
|
|
return _chmod (map_w32_filename (path, NULL), mode);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-06-24 10:39:56 +00:00
|
|
|
|
int
|
|
|
|
|
sys_chown (const char *path, uid_t owner, gid_t group)
|
|
|
|
|
{
|
2008-04-05 14:32:28 +00:00
|
|
|
|
if (sys_chmod (path, S_IREAD) == -1) /* check if file exists */
|
2005-06-24 10:39:56 +00:00
|
|
|
|
return -1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int
|
|
|
|
|
sys_creat (const char * path, int mode)
|
|
|
|
|
{
|
1996-11-19 04:59:23 +00:00
|
|
|
|
return _creat (map_w32_filename (path, NULL), mode);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *
|
|
|
|
|
sys_fopen(const char * path, const char * mode)
|
|
|
|
|
{
|
|
|
|
|
int fd;
|
|
|
|
|
int oflag;
|
|
|
|
|
const char * mode_save = mode;
|
|
|
|
|
|
|
|
|
|
/* Force all file handles to be non-inheritable. This is necessary to
|
|
|
|
|
ensure child processes don't unwittingly inherit handles that might
|
|
|
|
|
prevent future file access. */
|
|
|
|
|
|
|
|
|
|
if (mode[0] == 'r')
|
|
|
|
|
oflag = O_RDONLY;
|
|
|
|
|
else if (mode[0] == 'w' || mode[0] == 'a')
|
|
|
|
|
oflag = O_WRONLY | O_CREAT | O_TRUNC;
|
1994-11-01 10:27:02 +00:00
|
|
|
|
else
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
/* Only do simplistic option parsing. */
|
|
|
|
|
while (*++mode)
|
|
|
|
|
if (mode[0] == '+')
|
|
|
|
|
{
|
|
|
|
|
oflag &= ~(O_RDONLY | O_WRONLY);
|
|
|
|
|
oflag |= O_RDWR;
|
|
|
|
|
}
|
|
|
|
|
else if (mode[0] == 'b')
|
|
|
|
|
{
|
|
|
|
|
oflag &= ~O_TEXT;
|
|
|
|
|
oflag |= O_BINARY;
|
|
|
|
|
}
|
|
|
|
|
else if (mode[0] == 't')
|
|
|
|
|
{
|
|
|
|
|
oflag &= ~O_BINARY;
|
|
|
|
|
oflag |= O_TEXT;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
|
1996-11-19 04:59:23 +00:00
|
|
|
|
fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (fd < 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
return _fdopen (fd, mode_save);
|
1994-11-01 10:27:02 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* This only works on NTFS volumes, but is useful to have. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int
|
1997-09-03 00:43:20 +00:00
|
|
|
|
sys_link (const char * old, const char * new)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
1997-09-03 00:43:20 +00:00
|
|
|
|
HANDLE fileh;
|
|
|
|
|
int result = -1;
|
|
|
|
|
char oldname[MAX_PATH], newname[MAX_PATH];
|
|
|
|
|
|
|
|
|
|
if (old == NULL || new == NULL)
|
|
|
|
|
{
|
|
|
|
|
errno = ENOENT;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
strcpy (oldname, map_w32_filename (old, NULL));
|
|
|
|
|
strcpy (newname, map_w32_filename (new, NULL));
|
|
|
|
|
|
|
|
|
|
fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
|
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
|
|
|
|
if (fileh != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
int wlen;
|
|
|
|
|
|
|
|
|
|
/* Confusingly, the "alternate" stream name field does not apply
|
|
|
|
|
when restoring a hard link, and instead contains the actual
|
|
|
|
|
stream data for the link (ie. the name of the link to create).
|
|
|
|
|
The WIN32_STREAM_ID structure before the cStreamName field is
|
|
|
|
|
the stream header, which is then immediately followed by the
|
|
|
|
|
stream data. */
|
|
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
WIN32_STREAM_ID wid;
|
|
|
|
|
WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
|
|
|
|
|
} data;
|
|
|
|
|
|
|
|
|
|
wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
|
|
|
|
|
data.wid.cStreamName, MAX_PATH);
|
|
|
|
|
if (wlen > 0)
|
|
|
|
|
{
|
|
|
|
|
LPVOID context = NULL;
|
|
|
|
|
DWORD wbytes = 0;
|
|
|
|
|
|
|
|
|
|
data.wid.dwStreamId = BACKUP_LINK;
|
|
|
|
|
data.wid.dwStreamAttributes = 0;
|
|
|
|
|
data.wid.Size.LowPart = wlen * sizeof(WCHAR);
|
|
|
|
|
data.wid.Size.HighPart = 0;
|
|
|
|
|
data.wid.dwStreamNameSize = 0;
|
|
|
|
|
|
|
|
|
|
if (BackupWrite (fileh, (LPBYTE)&data,
|
|
|
|
|
offsetof (WIN32_STREAM_ID, cStreamName)
|
|
|
|
|
+ data.wid.Size.LowPart,
|
|
|
|
|
&wbytes, FALSE, FALSE, &context)
|
|
|
|
|
&& BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
|
|
|
|
|
{
|
|
|
|
|
/* succeeded */
|
|
|
|
|
result = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Should try mapping GetLastError to errno; for now just
|
|
|
|
|
indicate a general error (eg. links not supported). */
|
|
|
|
|
errno = EINVAL; // perhaps EMLINK?
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle (fileh);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
errno = ENOENT;
|
|
|
|
|
|
|
|
|
|
return result;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_mkdir (const char * path)
|
|
|
|
|
{
|
1996-11-19 04:59:23 +00:00
|
|
|
|
return _mkdir (map_w32_filename (path, NULL));
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-06-07 23:07:00 +00:00
|
|
|
|
/* Because of long name mapping issues, we need to implement this
|
|
|
|
|
ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
|
|
|
|
|
a unique name, instead of setting the input template to an empty
|
|
|
|
|
string.
|
|
|
|
|
|
|
|
|
|
Standard algorithm seems to be use pid or tid with a letter on the
|
|
|
|
|
front (in place of the 6 X's) and cycle through the letters to find a
|
|
|
|
|
unique name. We extend that to allow any reasonable character as the
|
|
|
|
|
first of the 6 X's. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
char *
|
|
|
|
|
sys_mktemp (char * template)
|
|
|
|
|
{
|
1996-06-07 23:07:00 +00:00
|
|
|
|
char * p;
|
|
|
|
|
int i;
|
|
|
|
|
unsigned uid = GetCurrentThreadId ();
|
|
|
|
|
static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
|
|
|
|
|
|
|
|
|
|
if (template == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
p = template + strlen (template);
|
|
|
|
|
i = 5;
|
|
|
|
|
/* replace up to the last 5 X's with uid in decimal */
|
|
|
|
|
while (--p >= template && p[0] == 'X' && --i >= 0)
|
|
|
|
|
{
|
|
|
|
|
p[0] = '0' + uid % 10;
|
|
|
|
|
uid /= 10;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (i < 0 && p[0] == 'X')
|
|
|
|
|
{
|
|
|
|
|
i = 0;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
int save_errno = errno;
|
|
|
|
|
p[0] = first_char[i];
|
|
|
|
|
if (sys_access (template, 0) < 0)
|
|
|
|
|
{
|
|
|
|
|
errno = save_errno;
|
|
|
|
|
return template;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (++i < sizeof (first_char));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Template is badly formed or else we can't generate a unique name,
|
|
|
|
|
so return empty string */
|
|
|
|
|
template[0] = 0;
|
|
|
|
|
return template;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_open (const char * path, int oflag, int mode)
|
|
|
|
|
{
|
2001-04-10 12:15:25 +00:00
|
|
|
|
const char* mpath = map_w32_filename (path, NULL);
|
|
|
|
|
/* Try to open file without _O_CREAT, to be able to write to hidden
|
|
|
|
|
and system files. Force all file handles to be
|
|
|
|
|
non-inheritable. */
|
|
|
|
|
int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
|
|
|
|
|
if (res >= 0)
|
|
|
|
|
return res;
|
|
|
|
|
return _open (mpath, oflag | _O_NOINHERIT, mode);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_rename (const char * oldname, const char * newname)
|
|
|
|
|
{
|
2000-12-17 23:14:55 +00:00
|
|
|
|
BOOL result;
|
1998-06-05 16:08:32 +00:00
|
|
|
|
char temp[MAX_PATH];
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1997-01-20 00:38:22 +00:00
|
|
|
|
/* MoveFile on Windows 95 doesn't correctly change the short file name
|
1996-07-07 01:59:24 +00:00
|
|
|
|
alias in a number of circumstances (it is not easy to predict when
|
|
|
|
|
just by looking at oldname and newname, unfortunately). In these
|
|
|
|
|
cases, renaming through a temporary name avoids the problem.
|
|
|
|
|
|
1997-01-20 00:38:22 +00:00
|
|
|
|
A second problem on Windows 95 is that renaming through a temp name when
|
1996-07-07 01:59:24 +00:00
|
|
|
|
newname is uppercase fails (the final long name ends up in
|
|
|
|
|
lowercase, although the short alias might be uppercase) UNLESS the
|
|
|
|
|
long temp name is not 8.3.
|
|
|
|
|
|
1997-01-20 00:38:22 +00:00
|
|
|
|
So, on Windows 95 we always rename through a temp name, and we make sure
|
1996-07-07 01:59:24 +00:00
|
|
|
|
the temp name has a long extension to ensure correct renaming. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1996-11-19 04:59:23 +00:00
|
|
|
|
strcpy (temp, map_w32_filename (oldname, NULL));
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
if (os_subtype == OS_WIN95)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
1998-06-05 16:08:32 +00:00
|
|
|
|
char * o;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
char * p;
|
1998-06-05 16:08:32 +00:00
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
oldname = map_w32_filename (oldname, NULL);
|
|
|
|
|
if (o = strrchr (oldname, '\\'))
|
|
|
|
|
o++;
|
|
|
|
|
else
|
|
|
|
|
o = (char *) oldname;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (p = strrchr (temp, '\\'))
|
|
|
|
|
p++;
|
|
|
|
|
else
|
|
|
|
|
p = temp;
|
1998-06-05 16:08:32 +00:00
|
|
|
|
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
/* Force temp name to require a manufactured 8.3 alias - this
|
|
|
|
|
seems to make the second rename work properly. */
|
1998-06-16 04:33:08 +00:00
|
|
|
|
sprintf (p, "_.%s.%u", o, i);
|
1998-06-05 16:08:32 +00:00
|
|
|
|
i++;
|
1998-06-10 21:00:39 +00:00
|
|
|
|
result = rename (oldname, temp);
|
1998-06-05 16:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
/* This loop must surely terminate! */
|
2000-12-17 23:14:55 +00:00
|
|
|
|
while (result < 0 && errno == EEXIST);
|
1998-06-10 21:00:39 +00:00
|
|
|
|
if (result < 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-27 07:34:53 +00:00
|
|
|
|
/* Emulate Unix behavior - newname is deleted if it already exists
|
1996-07-07 01:59:24 +00:00
|
|
|
|
(at least if it is a file; don't do this for directories).
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
1998-06-05 16:08:32 +00:00
|
|
|
|
Since we mustn't do this if we are just changing the case of the
|
|
|
|
|
file name (we would end up deleting the file we are trying to
|
|
|
|
|
rename!), we let rename detect if the destination file already
|
|
|
|
|
exists - that way we avoid the possible pitfalls of trying to
|
|
|
|
|
determine ourselves whether two names really refer to the same
|
|
|
|
|
file, which is not always possible in the general case. (Consider
|
|
|
|
|
all the permutations of shared or subst'd drives, etc.) */
|
|
|
|
|
|
|
|
|
|
newname = map_w32_filename (newname, NULL);
|
1998-05-30 23:41:57 +00:00
|
|
|
|
result = rename (temp, newname);
|
1998-06-05 16:08:32 +00:00
|
|
|
|
|
|
|
|
|
if (result < 0
|
2000-12-17 23:14:55 +00:00
|
|
|
|
&& errno == EEXIST
|
1998-06-05 16:08:32 +00:00
|
|
|
|
&& _chmod (newname, 0666) == 0
|
|
|
|
|
&& _unlink (newname) == 0)
|
|
|
|
|
result = rename (temp, newname);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1998-05-30 23:41:57 +00:00
|
|
|
|
return result;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_rmdir (const char * path)
|
|
|
|
|
{
|
1996-11-19 04:59:23 +00:00
|
|
|
|
return _rmdir (map_w32_filename (path, NULL));
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_unlink (const char * path)
|
|
|
|
|
{
|
1998-04-23 23:41:12 +00:00
|
|
|
|
path = map_w32_filename (path, NULL);
|
|
|
|
|
|
|
|
|
|
/* On Unix, unlink works without write permission. */
|
|
|
|
|
_chmod (path, 0666);
|
|
|
|
|
return _unlink (path);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FILETIME utc_base_ft;
|
2009-01-04 11:30:13 +00:00
|
|
|
|
static ULONGLONG utc_base; /* In 100ns units */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
static int init = 0;
|
|
|
|
|
|
2009-01-04 11:30:13 +00:00
|
|
|
|
#define FILETIME_TO_U64(result, ft) \
|
|
|
|
|
do { \
|
|
|
|
|
ULARGE_INTEGER uiTemp; \
|
|
|
|
|
uiTemp.LowPart = (ft).dwLowDateTime; \
|
|
|
|
|
uiTemp.HighPart = (ft).dwHighDateTime; \
|
|
|
|
|
result = uiTemp.QuadPart; \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
initialize_utc_base ()
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
2009-01-04 11:30:13 +00:00
|
|
|
|
/* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
|
|
|
|
|
SYSTEMTIME st;
|
|
|
|
|
|
|
|
|
|
st.wYear = 1970;
|
|
|
|
|
st.wMonth = 1;
|
|
|
|
|
st.wDay = 1;
|
|
|
|
|
st.wHour = 0;
|
|
|
|
|
st.wMinute = 0;
|
|
|
|
|
st.wSecond = 0;
|
|
|
|
|
st.wMilliseconds = 0;
|
|
|
|
|
|
|
|
|
|
SystemTimeToFileTime (&st, &utc_base_ft);
|
|
|
|
|
FILETIME_TO_U64 (utc_base, utc_base_ft);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
static time_t
|
|
|
|
|
convert_time (FILETIME ft)
|
|
|
|
|
{
|
2009-01-04 11:30:13 +00:00
|
|
|
|
ULONGLONG tmp;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (!init)
|
|
|
|
|
{
|
2009-01-04 11:30:13 +00:00
|
|
|
|
initialize_utc_base();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
init = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (CompareFileTime (&ft, &utc_base_ft) < 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2009-01-04 11:30:13 +00:00
|
|
|
|
FILETIME_TO_U64 (tmp, ft);
|
|
|
|
|
return (time_t) ((tmp - utc_base) / 10000000L);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
void
|
|
|
|
|
convert_from_time_t (time_t time, FILETIME * pft)
|
|
|
|
|
{
|
2009-01-04 11:30:13 +00:00
|
|
|
|
ULARGE_INTEGER tmp;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (!init)
|
|
|
|
|
{
|
2009-01-04 11:30:13 +00:00
|
|
|
|
initialize_utc_base ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
init = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* time in 100ns units since 1-Jan-1601 */
|
2009-01-04 11:30:13 +00:00
|
|
|
|
tmp.QuadPart = (ULONGLONG) time * 10000000L + utc_base;
|
|
|
|
|
pft->dwHighDateTime = tmp.HighPart;
|
|
|
|
|
pft->dwLowDateTime = tmp.LowPart;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#if 0
|
|
|
|
|
/* No reason to keep this; faking inode values either by hashing or even
|
|
|
|
|
using the file index from GetInformationByHandle, is not perfect and
|
|
|
|
|
so by default Emacs doesn't use the inode values on Windows.
|
|
|
|
|
Instead, we now determine file-truename correctly (except for
|
|
|
|
|
possible drive aliasing etc). */
|
|
|
|
|
|
|
|
|
|
/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
static unsigned
|
1997-09-03 00:43:20 +00:00
|
|
|
|
hashval (const unsigned char * str)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned h = 0;
|
|
|
|
|
while (*str)
|
|
|
|
|
{
|
|
|
|
|
h = (h << 4) + *str++;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
h ^= (h >> 28);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return the hash value of the canonical pathname, excluding the
|
|
|
|
|
drive/UNC header, to get a hopefully unique inode number. */
|
1997-09-03 00:43:20 +00:00
|
|
|
|
static DWORD
|
1996-05-03 18:32:52 +00:00
|
|
|
|
generate_inode_val (const char * name)
|
|
|
|
|
{
|
|
|
|
|
char fullname[ MAX_PATH ];
|
|
|
|
|
char * p;
|
|
|
|
|
unsigned hash;
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Get the truly canonical filename, if it exists. (Note: this
|
|
|
|
|
doesn't resolve aliasing due to subst commands, or recognise hard
|
|
|
|
|
links. */
|
|
|
|
|
if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
parse_root (fullname, &p);
|
1996-11-19 04:59:23 +00:00
|
|
|
|
/* Normal W32 filesystems are still case insensitive. */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
_strlwr (p);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
return hashval (p);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
static PSECURITY_DESCRIPTOR
|
|
|
|
|
get_file_security_desc (const char *fname)
|
|
|
|
|
{
|
|
|
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
|
|
|
DWORD sd_len, err;
|
|
|
|
|
SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION
|
|
|
|
|
| GROUP_SECURITY_INFORMATION /* | DACL_SECURITY_INFORMATION */ ;
|
|
|
|
|
|
|
|
|
|
if (!get_file_security (fname, si, psd, 0, &sd_len))
|
|
|
|
|
{
|
|
|
|
|
err = GetLastError ();
|
|
|
|
|
if (err != ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
psd = xmalloc (sd_len);
|
|
|
|
|
if (!get_file_security (fname, si, psd, sd_len, &sd_len))
|
|
|
|
|
{
|
|
|
|
|
xfree (psd);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return psd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
|
get_rid (PSID sid)
|
|
|
|
|
{
|
|
|
|
|
unsigned n_subauthorities;
|
|
|
|
|
|
|
|
|
|
/* Use the last sub-authority value of the RID, the relative
|
|
|
|
|
portion of the SID, as user/group ID. */
|
|
|
|
|
n_subauthorities = *get_sid_sub_authority_count (sid);
|
|
|
|
|
if (n_subauthorities < 1)
|
|
|
|
|
return 0; /* the "World" RID */
|
|
|
|
|
return *get_sid_sub_authority (sid, n_subauthorities - 1);
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-15 16:00:19 +00:00
|
|
|
|
/* Caching SID and account values for faster lokup. */
|
|
|
|
|
|
|
|
|
|
#ifdef __GNUC__
|
|
|
|
|
# define FLEXIBLE_ARRAY_MEMBER
|
|
|
|
|
#else
|
|
|
|
|
# define FLEXIBLE_ARRAY_MEMBER 1
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
struct w32_id {
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned rid;
|
2008-08-15 16:00:19 +00:00
|
|
|
|
struct w32_id *next;
|
|
|
|
|
char name[GNLEN+1];
|
|
|
|
|
unsigned char sid[FLEXIBLE_ARRAY_MEMBER];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct w32_id *w32_idlist;
|
|
|
|
|
|
|
|
|
|
static int
|
2009-03-21 11:31:50 +00:00
|
|
|
|
w32_cached_id (PSID sid, unsigned *id, char *name)
|
2008-08-15 16:00:19 +00:00
|
|
|
|
{
|
|
|
|
|
struct w32_id *tail, *found;
|
|
|
|
|
|
|
|
|
|
for (found = NULL, tail = w32_idlist; tail; tail = tail->next)
|
|
|
|
|
{
|
|
|
|
|
if (equal_sid ((PSID)tail->sid, sid))
|
|
|
|
|
{
|
|
|
|
|
found = tail;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (found)
|
|
|
|
|
{
|
|
|
|
|
*id = found->rid;
|
|
|
|
|
strcpy (name, found->name);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2009-03-21 11:31:50 +00:00
|
|
|
|
w32_add_to_cache (PSID sid, unsigned id, char *name)
|
2008-08-15 16:00:19 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD sid_len;
|
|
|
|
|
struct w32_id *new_entry;
|
|
|
|
|
|
|
|
|
|
/* We don't want to leave behind stale cache from when Emacs was
|
|
|
|
|
dumped. */
|
|
|
|
|
if (initialized)
|
|
|
|
|
{
|
|
|
|
|
sid_len = get_length_sid (sid);
|
|
|
|
|
new_entry = xmalloc (offsetof (struct w32_id, sid) + sid_len);
|
|
|
|
|
if (new_entry)
|
|
|
|
|
{
|
|
|
|
|
new_entry->rid = id;
|
|
|
|
|
strcpy (new_entry->name, name);
|
|
|
|
|
copy_sid (sid_len, (PSID)new_entry->sid, sid);
|
|
|
|
|
new_entry->next = w32_idlist;
|
|
|
|
|
w32_idlist = new_entry;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
#define UID 1
|
|
|
|
|
#define GID 2
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
get_name_and_id (PSECURITY_DESCRIPTOR psd, const char *fname,
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned *id, char *nm, int what)
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
{
|
|
|
|
|
PSID sid = NULL;
|
|
|
|
|
char machine[MAX_COMPUTERNAME_LENGTH+1];
|
|
|
|
|
BOOL dflt;
|
|
|
|
|
SID_NAME_USE ignore;
|
|
|
|
|
char name[UNLEN+1];
|
|
|
|
|
DWORD name_len = sizeof (name);
|
|
|
|
|
char domain[1024];
|
|
|
|
|
DWORD domain_len = sizeof(domain);
|
|
|
|
|
char *mp = NULL;
|
|
|
|
|
int use_dflt = 0;
|
|
|
|
|
int result;
|
|
|
|
|
|
|
|
|
|
if (what == UID)
|
|
|
|
|
result = get_security_descriptor_owner (psd, &sid, &dflt);
|
|
|
|
|
else if (what == GID)
|
|
|
|
|
result = get_security_descriptor_group (psd, &sid, &dflt);
|
|
|
|
|
else
|
|
|
|
|
result = 0;
|
|
|
|
|
|
|
|
|
|
if (!result || !is_valid_sid (sid))
|
|
|
|
|
use_dflt = 1;
|
2008-08-15 16:00:19 +00:00
|
|
|
|
else if (!w32_cached_id (sid, id, nm))
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
{
|
|
|
|
|
/* If FNAME is a UNC, we need to lookup account on the
|
|
|
|
|
specified machine. */
|
|
|
|
|
if (IS_DIRECTORY_SEP (fname[0]) && IS_DIRECTORY_SEP (fname[1])
|
|
|
|
|
&& fname[2] != '\0')
|
|
|
|
|
{
|
|
|
|
|
const char *s;
|
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
|
|
for (s = fname + 2, p = machine;
|
|
|
|
|
*s && !IS_DIRECTORY_SEP (*s); s++, p++)
|
|
|
|
|
*p = *s;
|
|
|
|
|
*p = '\0';
|
|
|
|
|
mp = machine;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!lookup_account_sid (mp, sid, name, &name_len,
|
|
|
|
|
domain, &domain_len, &ignore)
|
|
|
|
|
|| name_len > UNLEN+1)
|
|
|
|
|
use_dflt = 1;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
*id = get_rid (sid);
|
|
|
|
|
strcpy (nm, name);
|
2008-08-15 16:00:19 +00:00
|
|
|
|
w32_add_to_cache (sid, *id, name);
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return use_dflt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
get_file_owner_and_group (
|
|
|
|
|
PSECURITY_DESCRIPTOR psd,
|
|
|
|
|
const char *fname,
|
|
|
|
|
struct stat *st)
|
|
|
|
|
{
|
|
|
|
|
int dflt_usr = 0, dflt_grp = 0;
|
|
|
|
|
|
|
|
|
|
if (!psd)
|
|
|
|
|
{
|
|
|
|
|
dflt_usr = 1;
|
|
|
|
|
dflt_grp = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (get_name_and_id (psd, fname, &st->st_uid, st->st_uname, UID))
|
|
|
|
|
dflt_usr = 1;
|
|
|
|
|
if (get_name_and_id (psd, fname, &st->st_gid, st->st_gname, GID))
|
|
|
|
|
dflt_grp = 1;
|
|
|
|
|
}
|
|
|
|
|
/* Consider files to belong to current user/group, if we cannot get
|
|
|
|
|
more accurate information. */
|
|
|
|
|
if (dflt_usr)
|
|
|
|
|
{
|
|
|
|
|
st->st_uid = dflt_passwd.pw_uid;
|
|
|
|
|
strcpy (st->st_uname, dflt_passwd.pw_name);
|
|
|
|
|
}
|
|
|
|
|
if (dflt_grp)
|
|
|
|
|
{
|
|
|
|
|
st->st_gid = dflt_passwd.pw_gid;
|
|
|
|
|
strcpy (st->st_gname, dflt_group.gr_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-11 15:44:36 +00:00
|
|
|
|
/* Return non-zero if NAME is a potentially slow filesystem. */
|
|
|
|
|
int
|
|
|
|
|
is_slow_fs (const char *name)
|
|
|
|
|
{
|
|
|
|
|
char drive_root[4];
|
|
|
|
|
UINT devtype;
|
|
|
|
|
|
|
|
|
|
if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
|
|
|
|
|
devtype = DRIVE_REMOTE; /* assume UNC name is remote */
|
|
|
|
|
else if (!(strlen (name) >= 2 && IS_DEVICE_SEP (name[1])))
|
|
|
|
|
devtype = GetDriveType (NULL); /* use root of current drive */
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* GetDriveType needs the root directory of the drive. */
|
|
|
|
|
strncpy (drive_root, name, 2);
|
|
|
|
|
drive_root[2] = '\\';
|
|
|
|
|
drive_root[3] = '\0';
|
|
|
|
|
devtype = GetDriveType (drive_root);
|
|
|
|
|
}
|
|
|
|
|
return !(devtype == DRIVE_FIXED || devtype == DRIVE_RAMDISK);
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* MSVC stat function can't cope with UNC names and has other bugs, so
|
|
|
|
|
replace it with our own. This also allows us to calculate consistent
|
|
|
|
|
inode values without hacks in the main Emacs code. */
|
|
|
|
|
int
|
|
|
|
|
stat (const char * path, struct stat * buf)
|
|
|
|
|
{
|
1998-05-30 23:41:57 +00:00
|
|
|
|
char *name, *r;
|
2008-08-15 13:54:14 +00:00
|
|
|
|
char drive_root[4];
|
|
|
|
|
UINT devtype;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
WIN32_FIND_DATA wfd;
|
|
|
|
|
HANDLE fh;
|
2008-04-05 14:32:28 +00:00
|
|
|
|
unsigned __int64 fake_inode;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int permission;
|
|
|
|
|
int len;
|
|
|
|
|
int rootdir = FALSE;
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (path == NULL || buf == NULL)
|
|
|
|
|
{
|
|
|
|
|
errno = EFAULT;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
1996-11-19 04:59:23 +00:00
|
|
|
|
name = (char *) map_w32_filename (path, &path);
|
2007-02-23 18:40:41 +00:00
|
|
|
|
/* Must be valid filename, no wild cards or other invalid
|
|
|
|
|
characters. We use _mbspbrk to support multibyte strings that
|
|
|
|
|
might look to strpbrk as if they included literal *, ?, and other
|
|
|
|
|
characters mentioned below that are disallowed by Windows
|
|
|
|
|
filesystems. */
|
|
|
|
|
if (_mbspbrk (name, "*?|<>\""))
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
errno = ENOENT;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
1998-05-30 23:41:57 +00:00
|
|
|
|
/* If name is "c:/.." or "/.." then stat "c:/" or "/". */
|
|
|
|
|
r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
|
|
|
|
|
if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
|
|
|
|
|
{
|
|
|
|
|
r[1] = r[2] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Remove trailing directory separator, unless name is the root
|
|
|
|
|
directory of a drive or UNC volume in which case ensure there
|
|
|
|
|
is a trailing separator. */
|
|
|
|
|
len = strlen (name);
|
|
|
|
|
rootdir = (path >= name + len - 1
|
|
|
|
|
&& (IS_DIRECTORY_SEP (*path) || *path == 0));
|
|
|
|
|
name = strcpy (alloca (len + 2), name);
|
|
|
|
|
|
1998-06-17 04:22:58 +00:00
|
|
|
|
if (is_unc_volume (name))
|
|
|
|
|
{
|
|
|
|
|
DWORD attrs = unc_volume_file_attributes (name);
|
|
|
|
|
|
|
|
|
|
if (attrs == -1)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
memset (&wfd, 0, sizeof (wfd));
|
|
|
|
|
wfd.dwFileAttributes = attrs;
|
|
|
|
|
wfd.ftCreationTime = utc_base_ft;
|
|
|
|
|
wfd.ftLastAccessTime = utc_base_ft;
|
|
|
|
|
wfd.ftLastWriteTime = utc_base_ft;
|
|
|
|
|
strcpy (wfd.cFileName, name);
|
|
|
|
|
}
|
|
|
|
|
else if (rootdir)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
if (!IS_DIRECTORY_SEP (name[len-1]))
|
|
|
|
|
strcat (name, "\\");
|
|
|
|
|
if (GetDriveType (name) < 2)
|
|
|
|
|
{
|
|
|
|
|
errno = ENOENT;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
memset (&wfd, 0, sizeof (wfd));
|
|
|
|
|
wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
|
wfd.ftCreationTime = utc_base_ft;
|
|
|
|
|
wfd.ftLastAccessTime = utc_base_ft;
|
|
|
|
|
wfd.ftLastWriteTime = utc_base_ft;
|
|
|
|
|
strcpy (wfd.cFileName, name);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (IS_DIRECTORY_SEP (name[len-1]))
|
|
|
|
|
name[len - 1] = 0;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
|
|
|
|
/* (This is hacky, but helps when doing file completions on
|
|
|
|
|
network drives.) Optimize by using information available from
|
|
|
|
|
active readdir if possible. */
|
1999-08-06 20:40:36 +00:00
|
|
|
|
len = strlen (dir_pathname);
|
|
|
|
|
if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
|
|
|
|
|
len--;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
if (dir_find_handle != INVALID_HANDLE_VALUE
|
1999-08-06 20:40:36 +00:00
|
|
|
|
&& strnicmp (name, dir_pathname, len) == 0
|
1997-09-03 00:43:20 +00:00
|
|
|
|
&& IS_DIRECTORY_SEP (name[len])
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
&& xstrcasecmp (name + len + 1, dir_static.d_name) == 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* This was the last entry returned by readdir. */
|
|
|
|
|
wfd = dir_find_data;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-01-28 17:44:11 +00:00
|
|
|
|
logon_network_drive (name);
|
2008-01-26 01:08:53 +00:00
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
fh = FindFirstFile (name, &wfd);
|
|
|
|
|
if (fh == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
errno = ENOENT;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
FindClose (fh);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
if (!(NILP (Vw32_get_true_file_attributes)
|
2009-07-11 20:31:27 +00:00
|
|
|
|
|| (EQ (Vw32_get_true_file_attributes, Qlocal) && is_slow_fs (name)))
|
2002-04-28 18:52:26 +00:00
|
|
|
|
/* No access rights required to get info. */
|
|
|
|
|
&& (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
|
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS, NULL))
|
|
|
|
|
!= INVALID_HANDLE_VALUE)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
/* This is more accurate in terms of gettting the correct number
|
2007-06-20 08:31:09 +00:00
|
|
|
|
of links, but is quite slow (it is noticeable when Emacs is
|
1996-05-03 18:32:52 +00:00
|
|
|
|
making a list of file name completions). */
|
|
|
|
|
BY_HANDLE_FILE_INFORMATION info;
|
|
|
|
|
|
|
|
|
|
if (GetFileInformationByHandle (fh, &info))
|
|
|
|
|
{
|
|
|
|
|
buf->st_nlink = info.nNumberOfLinks;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Might as well use file index to fake inode values, but this
|
|
|
|
|
is not guaranteed to be unique unless we keep a handle open
|
|
|
|
|
all the time (even then there are situations where it is
|
|
|
|
|
not unique). Reputedly, there are at most 48 bits of info
|
|
|
|
|
(on NTFS, presumably less on FAT). */
|
2008-04-05 14:32:28 +00:00
|
|
|
|
fake_inode = info.nFileIndexHigh;
|
|
|
|
|
fake_inode <<= 32;
|
|
|
|
|
fake_inode += info.nFileIndexLow;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1998-11-03 22:39:04 +00:00
|
|
|
|
buf->st_nlink = 1;
|
|
|
|
|
fake_inode = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2002-04-28 18:52:26 +00:00
|
|
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
1998-11-03 22:39:04 +00:00
|
|
|
|
{
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFDIR;
|
2002-04-28 18:52:26 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (GetFileType (fh))
|
|
|
|
|
{
|
|
|
|
|
case FILE_TYPE_DISK:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFREG;
|
2002-04-28 18:52:26 +00:00
|
|
|
|
break;
|
|
|
|
|
case FILE_TYPE_PIPE:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFIFO;
|
2002-04-28 18:52:26 +00:00
|
|
|
|
break;
|
|
|
|
|
case FILE_TYPE_CHAR:
|
|
|
|
|
case FILE_TYPE_UNKNOWN:
|
|
|
|
|
default:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFCHR;
|
2002-04-28 18:52:26 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
1998-11-03 22:39:04 +00:00
|
|
|
|
CloseHandle (fh);
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
psd = get_file_security_desc (name);
|
|
|
|
|
get_file_owner_and_group (psd, name, buf);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Don't bother to make this information more accurate. */
|
2002-04-28 18:52:26 +00:00
|
|
|
|
buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
2008-04-05 14:32:28 +00:00
|
|
|
|
S_IFDIR : S_IFREG;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
buf->st_nlink = 1;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
fake_inode = 0;
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
|
|
|
|
|
get_file_owner_and_group (NULL, name, buf);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
2008-06-02 06:09:17 +00:00
|
|
|
|
xfree (psd);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
/* Not sure if there is any point in this. */
|
|
|
|
|
if (!NILP (Vw32_generate_fake_inodes))
|
|
|
|
|
fake_inode = generate_inode_val (name);
|
|
|
|
|
else if (fake_inode == 0)
|
|
|
|
|
{
|
|
|
|
|
/* For want of something better, try to make everything unique. */
|
|
|
|
|
static DWORD gen_num = 0;
|
|
|
|
|
fake_inode = ++gen_num;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* MSVC defines _ino_t to be short; other libc's might not. */
|
|
|
|
|
if (sizeof (buf->st_ino) == 2)
|
|
|
|
|
buf->st_ino = fake_inode ^ (fake_inode >> 16);
|
|
|
|
|
else
|
|
|
|
|
buf->st_ino = fake_inode;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
1996-11-19 04:59:23 +00:00
|
|
|
|
/* volume_info is set indirectly by map_w32_filename */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
buf->st_dev = volume_info.serialnum;
|
|
|
|
|
buf->st_rdev = volume_info.serialnum;
|
|
|
|
|
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
buf->st_size = wfd.nFileSizeHigh;
|
|
|
|
|
buf->st_size <<= 32;
|
|
|
|
|
buf->st_size += wfd.nFileSizeLow;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* Convert timestamps to Unix format. */
|
|
|
|
|
buf->st_mtime = convert_time (wfd.ftLastWriteTime);
|
|
|
|
|
buf->st_atime = convert_time (wfd.ftLastAccessTime);
|
|
|
|
|
if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
|
|
|
|
|
buf->st_ctime = convert_time (wfd.ftCreationTime);
|
|
|
|
|
if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
|
|
|
|
|
|
|
|
|
|
/* determine rwx permissions */
|
|
|
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission = S_IREAD;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
else
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission = S_IREAD | S_IWRITE;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission |= S_IEXEC;
|
1998-06-05 16:08:32 +00:00
|
|
|
|
else if (is_exec (name))
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission |= S_IEXEC;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-23 23:41:12 +00:00
|
|
|
|
/* Provide fstat and utime as well as stat for consistent handling of
|
|
|
|
|
file timestamps. */
|
|
|
|
|
int
|
|
|
|
|
fstat (int desc, struct stat * buf)
|
|
|
|
|
{
|
|
|
|
|
HANDLE fh = (HANDLE) _get_osfhandle (desc);
|
|
|
|
|
BY_HANDLE_FILE_INFORMATION info;
|
2008-04-05 14:32:28 +00:00
|
|
|
|
unsigned __int64 fake_inode;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
int permission;
|
|
|
|
|
|
|
|
|
|
switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
|
|
|
|
|
{
|
|
|
|
|
case FILE_TYPE_DISK:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFREG;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
if (!GetFileInformationByHandle (fh, &info))
|
|
|
|
|
{
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case FILE_TYPE_PIPE:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFIFO;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
goto non_disk;
|
|
|
|
|
case FILE_TYPE_CHAR:
|
|
|
|
|
case FILE_TYPE_UNKNOWN:
|
|
|
|
|
default:
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFCHR;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
non_disk:
|
|
|
|
|
memset (&info, 0, sizeof (info));
|
|
|
|
|
info.dwFileAttributes = 0;
|
|
|
|
|
info.ftCreationTime = utc_base_ft;
|
|
|
|
|
info.ftLastAccessTime = utc_base_ft;
|
|
|
|
|
info.ftLastWriteTime = utc_base_ft;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
2008-04-05 14:32:28 +00:00
|
|
|
|
buf->st_mode = S_IFDIR;
|
2002-04-28 18:52:26 +00:00
|
|
|
|
|
|
|
|
|
buf->st_nlink = info.nNumberOfLinks;
|
|
|
|
|
/* Might as well use file index to fake inode values, but this
|
|
|
|
|
is not guaranteed to be unique unless we keep a handle open
|
|
|
|
|
all the time (even then there are situations where it is
|
|
|
|
|
not unique). Reputedly, there are at most 48 bits of info
|
|
|
|
|
(on NTFS, presumably less on FAT). */
|
2008-04-05 14:32:28 +00:00
|
|
|
|
fake_inode = info.nFileIndexHigh;
|
|
|
|
|
fake_inode <<= 32;
|
|
|
|
|
fake_inode += info.nFileIndexLow;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
|
|
|
|
|
/* MSVC defines _ino_t to be short; other libc's might not. */
|
|
|
|
|
if (sizeof (buf->st_ino) == 2)
|
|
|
|
|
buf->st_ino = fake_inode ^ (fake_inode >> 16);
|
|
|
|
|
else
|
|
|
|
|
buf->st_ino = fake_inode;
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
/* Consider files to belong to current user.
|
|
|
|
|
FIXME: this should use GetSecurityInfo API, but it is only
|
|
|
|
|
available for _WIN32_WINNT >= 0x501. */
|
2008-05-09 09:40:56 +00:00
|
|
|
|
buf->st_uid = dflt_passwd.pw_uid;
|
|
|
|
|
buf->st_gid = dflt_passwd.pw_gid;
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
strcpy (buf->st_uname, dflt_passwd.pw_name);
|
|
|
|
|
strcpy (buf->st_gname, dflt_group.gr_name);
|
1998-04-23 23:41:12 +00:00
|
|
|
|
|
|
|
|
|
buf->st_dev = info.dwVolumeSerialNumber;
|
|
|
|
|
buf->st_rdev = info.dwVolumeSerialNumber;
|
|
|
|
|
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
buf->st_size = info.nFileSizeHigh;
|
|
|
|
|
buf->st_size <<= 32;
|
|
|
|
|
buf->st_size += info.nFileSizeLow;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
|
|
|
|
|
/* Convert timestamps to Unix format. */
|
|
|
|
|
buf->st_mtime = convert_time (info.ftLastWriteTime);
|
|
|
|
|
buf->st_atime = convert_time (info.ftLastAccessTime);
|
|
|
|
|
if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
|
|
|
|
|
buf->st_ctime = convert_time (info.ftCreationTime);
|
|
|
|
|
if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
|
|
|
|
|
|
|
|
|
|
/* determine rwx permissions */
|
|
|
|
|
if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission = S_IREAD;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
else
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission = S_IREAD | S_IWRITE;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1998-04-23 23:41:12 +00:00
|
|
|
|
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission |= S_IEXEC;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#if 0 /* no way of knowing the filename */
|
|
|
|
|
char * p = strrchr (name, '.');
|
|
|
|
|
if (p != NULL &&
|
* dispextern.h, xfaces.c (xstrcasecmp): Renamed from xstricmp.
* dosfns.c, fileio.c, font.c, fontset.c, image.c, macfns.c:
* macterm.c, process.c, w32.c, w32fns.c, w32proc.c, xfaces.c:
* xfns.c, xfont.c: Callers changed.
2008-05-22 14:54:27 +00:00
|
|
|
|
(xstrcasecmp (p, ".exe") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".com") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".bat") == 0 ||
|
|
|
|
|
xstrcasecmp (p, ".cmd") == 0))
|
2008-04-05 14:32:28 +00:00
|
|
|
|
permission |= S_IEXEC;
|
1998-04-23 23:41:12 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
utime (const char *name, struct utimbuf *times)
|
|
|
|
|
{
|
|
|
|
|
struct utimbuf deftime;
|
|
|
|
|
HANDLE fh;
|
|
|
|
|
FILETIME mtime;
|
|
|
|
|
FILETIME atime;
|
|
|
|
|
|
|
|
|
|
if (times == NULL)
|
|
|
|
|
{
|
|
|
|
|
deftime.modtime = deftime.actime = time (NULL);
|
|
|
|
|
times = &deftime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Need write access to set times. */
|
|
|
|
|
fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
|
0, OPEN_EXISTING, 0, NULL);
|
|
|
|
|
if (fh)
|
|
|
|
|
{
|
|
|
|
|
convert_from_time_t (times->actime, &atime);
|
|
|
|
|
convert_from_time_t (times->modtime, &mtime);
|
|
|
|
|
if (!SetFileTime (fh, NULL, &atime, &mtime))
|
|
|
|
|
{
|
|
|
|
|
CloseHandle (fh);
|
|
|
|
|
errno = EACCES;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
CloseHandle (fh);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
errno = EINVAL;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
|
|
|
|
/* Support for browsing other processes and their attributes. See
|
|
|
|
|
process.c for the Lisp bindings. */
|
|
|
|
|
|
|
|
|
|
/* Helper wrapper functions. */
|
|
|
|
|
|
|
|
|
|
HANDLE WINAPI create_toolhelp32_snapshot(
|
|
|
|
|
DWORD Flags,
|
|
|
|
|
DWORD Ignored)
|
|
|
|
|
{
|
|
|
|
|
static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
|
|
|
|
|
|
|
|
|
|
if (g_b_init_create_toolhelp32_snapshot == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_create_toolhelp32_snapshot = 1;
|
|
|
|
|
s_pfn_Create_Toolhelp32_Snapshot = (CreateToolhelp32Snapshot_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"CreateToolhelp32Snapshot");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Create_Toolhelp32_Snapshot == NULL)
|
|
|
|
|
{
|
|
|
|
|
return INVALID_HANDLE_VALUE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI process32_first(
|
|
|
|
|
HANDLE hSnapshot,
|
|
|
|
|
LPPROCESSENTRY32 lppe)
|
|
|
|
|
{
|
|
|
|
|
static Process32First_Proc s_pfn_Process32_First = NULL;
|
|
|
|
|
|
|
|
|
|
if (g_b_init_process32_first == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_process32_first = 1;
|
|
|
|
|
s_pfn_Process32_First = (Process32First_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"Process32First");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Process32_First == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Process32_First (hSnapshot, lppe));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI process32_next(
|
|
|
|
|
HANDLE hSnapshot,
|
|
|
|
|
LPPROCESSENTRY32 lppe)
|
|
|
|
|
{
|
|
|
|
|
static Process32Next_Proc s_pfn_Process32_Next = NULL;
|
|
|
|
|
|
|
|
|
|
if (g_b_init_process32_next == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_process32_next = 1;
|
|
|
|
|
s_pfn_Process32_Next = (Process32Next_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"Process32Next");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Process32_Next == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (s_pfn_Process32_Next (hSnapshot, lppe));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI open_thread_token (
|
|
|
|
|
HANDLE ThreadHandle,
|
|
|
|
|
DWORD DesiredAccess,
|
|
|
|
|
BOOL OpenAsSelf,
|
|
|
|
|
PHANDLE TokenHandle)
|
|
|
|
|
{
|
|
|
|
|
static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
SetLastError (ERROR_NOT_SUPPORTED);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_open_thread_token == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_open_thread_token = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Open_Thread_Token =
|
|
|
|
|
(OpenThreadToken_Proc) GetProcAddress (hm_advapi32, "OpenThreadToken");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Open_Thread_Token == NULL)
|
|
|
|
|
{
|
|
|
|
|
SetLastError (ERROR_NOT_SUPPORTED);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
s_pfn_Open_Thread_Token (
|
|
|
|
|
ThreadHandle,
|
|
|
|
|
DesiredAccess,
|
|
|
|
|
OpenAsSelf,
|
|
|
|
|
TokenHandle)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI impersonate_self (
|
|
|
|
|
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
|
|
|
|
|
{
|
|
|
|
|
static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_impersonate_self == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_impersonate_self = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Impersonate_Self =
|
|
|
|
|
(ImpersonateSelf_Proc) GetProcAddress (hm_advapi32, "ImpersonateSelf");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Impersonate_Self == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Impersonate_Self (ImpersonationLevel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI revert_to_self (void)
|
|
|
|
|
{
|
|
|
|
|
static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
|
|
|
|
|
HMODULE hm_advapi32 = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_revert_to_self == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_revert_to_self = 1;
|
|
|
|
|
hm_advapi32 = LoadLibrary ("Advapi32.dll");
|
|
|
|
|
s_pfn_Revert_To_Self =
|
|
|
|
|
(RevertToSelf_Proc) GetProcAddress (hm_advapi32, "RevertToSelf");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Revert_To_Self == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Revert_To_Self ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_process_memory_info (
|
|
|
|
|
HANDLE h_proc,
|
|
|
|
|
PPROCESS_MEMORY_COUNTERS mem_counters,
|
|
|
|
|
DWORD bufsize)
|
|
|
|
|
{
|
|
|
|
|
static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
|
|
|
|
|
HMODULE hm_psapi = NULL;
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_process_memory_info == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_process_memory_info = 1;
|
|
|
|
|
hm_psapi = LoadLibrary ("Psapi.dll");
|
|
|
|
|
if (hm_psapi)
|
|
|
|
|
s_pfn_Get_Process_Memory_Info = (GetProcessMemoryInfo_Proc)
|
|
|
|
|
GetProcAddress (hm_psapi, "GetProcessMemoryInfo");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Process_Memory_Info == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI get_process_working_set_size (
|
|
|
|
|
HANDLE h_proc,
|
|
|
|
|
DWORD *minrss,
|
|
|
|
|
DWORD *maxrss)
|
|
|
|
|
{
|
|
|
|
|
static GetProcessWorkingSetSize_Proc
|
|
|
|
|
s_pfn_Get_Process_Working_Set_Size = NULL;
|
|
|
|
|
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_get_process_working_set_size == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_get_process_working_set_size = 1;
|
|
|
|
|
s_pfn_Get_Process_Working_Set_Size = (GetProcessWorkingSetSize_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"GetProcessWorkingSetSize");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Get_Process_Working_Set_Size == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI global_memory_status (
|
|
|
|
|
MEMORYSTATUS *buf)
|
|
|
|
|
{
|
|
|
|
|
static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
|
|
|
|
|
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_global_memory_status == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_global_memory_status = 1;
|
|
|
|
|
s_pfn_Global_Memory_Status = (GlobalMemoryStatus_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"GlobalMemoryStatus");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Global_Memory_Status == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Global_Memory_Status (buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL WINAPI global_memory_status_ex (
|
2008-08-15 12:49:09 +00:00
|
|
|
|
MEMORY_STATUS_EX *buf)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
|
|
|
|
|
|
|
|
|
|
if (is_windows_9x () == TRUE)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (g_b_init_global_memory_status_ex == 0)
|
|
|
|
|
{
|
|
|
|
|
g_b_init_global_memory_status_ex = 1;
|
|
|
|
|
s_pfn_Global_Memory_Status_Ex = (GlobalMemoryStatusEx_Proc)
|
|
|
|
|
GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"GlobalMemoryStatusEx");
|
|
|
|
|
}
|
|
|
|
|
if (s_pfn_Global_Memory_Status_Ex == NULL)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
return s_pfn_Global_Memory_Status_Ex (buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lisp_Object
|
Reorganize implementation of Flist_system_processes and
Fsystem_process_attributes. No functional changes.
* process.c: Don't #include pwd.h, grp.h and limits.h.
(Flist_system_processes): Just call list_system_processes.
(Fsystem_process_attributes): Just call system_process_attributes.
(procfs_list_system_processes, time_from_jiffies)
(ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
(procfs_get_total_memory, procfs_system_process_attributes): Move ...
* sysdep.c: ... here. Include pwd.h, grp.h and limits.h.
(list_system_processes): Rename from
procfs_list_system_processes. Enclose in #ifdef HAVE_PROCFS.
Provide a do nothing implementation.
(system_process_attributes): Rename from
procfs_list_system_processes.
(ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
(procfs_get_total_memory): Enclose in #ifdef GNU_LINUX.
* w32.c (list_system_processes): Rename from
w32_list_system_processes.
(system_process_attributes): Rename from
w32_system_process_attributes.
* s/gnu-linux.h (LISTPROC, PROCATTR): Remove.
* process.h (w32_list_system_processes)
(w32_system_process_attributes): Remove.
(list_system_processes, system_process_attributes): New
prototypes.
* config.nt (LISTPROC, PROCATTR): Remove.
2008-12-19 19:50:35 +00:00
|
|
|
|
list_system_processes ()
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
struct gcpro gcpro1;
|
|
|
|
|
Lisp_Object proclist = Qnil;
|
|
|
|
|
HANDLE h_snapshot;
|
|
|
|
|
|
|
|
|
|
h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
|
|
|
|
|
|
|
|
|
|
if (h_snapshot != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
PROCESSENTRY32 proc_entry;
|
|
|
|
|
DWORD proc_id;
|
|
|
|
|
BOOL res;
|
|
|
|
|
|
|
|
|
|
GCPRO1 (proclist);
|
|
|
|
|
|
|
|
|
|
proc_entry.dwSize = sizeof (PROCESSENTRY32);
|
|
|
|
|
for (res = process32_first (h_snapshot, &proc_entry); res;
|
|
|
|
|
res = process32_next (h_snapshot, &proc_entry))
|
|
|
|
|
{
|
|
|
|
|
proc_id = proc_entry.th32ProcessID;
|
|
|
|
|
proclist = Fcons (make_fixnum_or_float (proc_id), proclist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle (h_snapshot);
|
|
|
|
|
UNGCPRO;
|
|
|
|
|
proclist = Fnreverse (proclist);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return proclist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
enable_privilege (LPCTSTR priv_name, BOOL enable_p, TOKEN_PRIVILEGES *old_priv)
|
|
|
|
|
{
|
|
|
|
|
TOKEN_PRIVILEGES priv;
|
|
|
|
|
DWORD priv_size = sizeof (priv);
|
|
|
|
|
DWORD opriv_size = sizeof (*old_priv);
|
|
|
|
|
HANDLE h_token = NULL;
|
|
|
|
|
HANDLE h_thread = GetCurrentThread ();
|
|
|
|
|
int ret_val = 0;
|
|
|
|
|
BOOL res;
|
|
|
|
|
|
|
|
|
|
res = open_thread_token (h_thread,
|
|
|
|
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
|
|
|
|
FALSE, &h_token);
|
|
|
|
|
if (!res && GetLastError () == ERROR_NO_TOKEN)
|
|
|
|
|
{
|
|
|
|
|
if (impersonate_self (SecurityImpersonation))
|
|
|
|
|
res = open_thread_token (h_thread,
|
|
|
|
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
|
|
|
|
FALSE, &h_token);
|
|
|
|
|
}
|
|
|
|
|
if (res)
|
|
|
|
|
{
|
|
|
|
|
priv.PrivilegeCount = 1;
|
|
|
|
|
priv.Privileges[0].Attributes = enable_p ? SE_PRIVILEGE_ENABLED : 0;
|
|
|
|
|
LookupPrivilegeValue (NULL, priv_name, &priv.Privileges[0].Luid);
|
|
|
|
|
if (AdjustTokenPrivileges (h_token, FALSE, &priv, priv_size,
|
|
|
|
|
old_priv, &opriv_size)
|
|
|
|
|
&& GetLastError () != ERROR_NOT_ALL_ASSIGNED)
|
|
|
|
|
ret_val = 1;
|
|
|
|
|
}
|
|
|
|
|
if (h_token)
|
|
|
|
|
CloseHandle (h_token);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
restore_privilege (TOKEN_PRIVILEGES *priv)
|
|
|
|
|
{
|
|
|
|
|
DWORD priv_size = sizeof (*priv);
|
|
|
|
|
HANDLE h_token = NULL;
|
|
|
|
|
int ret_val = 0;
|
|
|
|
|
|
|
|
|
|
if (open_thread_token (GetCurrentThread (),
|
|
|
|
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
|
|
|
|
FALSE, &h_token))
|
|
|
|
|
{
|
|
|
|
|
if (AdjustTokenPrivileges (h_token, FALSE, priv, priv_size, NULL, NULL)
|
|
|
|
|
&& GetLastError () != ERROR_NOT_ALL_ASSIGNED)
|
|
|
|
|
ret_val = 1;
|
|
|
|
|
}
|
|
|
|
|
if (h_token)
|
|
|
|
|
CloseHandle (h_token);
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static Lisp_Object
|
|
|
|
|
ltime (time_sec, time_usec)
|
|
|
|
|
long time_sec, time_usec;
|
|
|
|
|
{
|
|
|
|
|
return list3 (make_number ((time_sec >> 16) & 0xffff),
|
|
|
|
|
make_number (time_sec & 0xffff),
|
|
|
|
|
make_number (time_usec));
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-04 11:30:13 +00:00
|
|
|
|
#define U64_TO_LISP_TIME(time) ltime ((time) / 1000000L, (time) % 1000000L)
|
|
|
|
|
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
static int
|
2009-01-02 15:08:57 +00:00
|
|
|
|
process_times (h_proc, ctime, etime, stime, utime, ttime, pcpu)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
HANDLE h_proc;
|
2009-01-02 15:08:57 +00:00
|
|
|
|
Lisp_Object *ctime, *etime, *stime, *utime, *ttime;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
double *pcpu;
|
|
|
|
|
{
|
|
|
|
|
FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
|
2009-01-04 11:30:13 +00:00
|
|
|
|
ULONGLONG tem1, tem2, tem3, tem;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
|
|
|
|
if (!h_proc
|
|
|
|
|
|| !get_process_times_fn
|
|
|
|
|
|| !(*get_process_times_fn)(h_proc, &ft_creation, &ft_exit,
|
|
|
|
|
&ft_kernel, &ft_user))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
GetSystemTimeAsFileTime (&ft_current);
|
|
|
|
|
|
2009-01-04 11:30:13 +00:00
|
|
|
|
FILETIME_TO_U64 (tem1, ft_kernel);
|
|
|
|
|
tem1 /= 10L;
|
|
|
|
|
*stime = U64_TO_LISP_TIME (tem1);
|
|
|
|
|
|
|
|
|
|
FILETIME_TO_U64 (tem2, ft_user);
|
|
|
|
|
tem2 /= 10L;
|
|
|
|
|
*utime = U64_TO_LISP_TIME (tem2);
|
|
|
|
|
|
|
|
|
|
tem3 = tem1 + tem2;
|
|
|
|
|
*ttime = U64_TO_LISP_TIME (tem3);
|
|
|
|
|
|
|
|
|
|
FILETIME_TO_U64 (tem, ft_creation);
|
2008-08-09 18:19:28 +00:00
|
|
|
|
/* Process no 4 (System) returns zero creation time. */
|
|
|
|
|
if (tem)
|
2009-01-04 11:30:13 +00:00
|
|
|
|
tem = (tem - utc_base) / 10L;
|
|
|
|
|
*ctime = U64_TO_LISP_TIME (tem);
|
|
|
|
|
|
2008-08-09 18:19:28 +00:00
|
|
|
|
if (tem)
|
2009-01-04 11:30:13 +00:00
|
|
|
|
{
|
|
|
|
|
FILETIME_TO_U64 (tem3, ft_current);
|
|
|
|
|
tem = (tem3 - utc_base) / 10L - tem;
|
|
|
|
|
}
|
|
|
|
|
*etime = U64_TO_LISP_TIME (tem);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
2008-08-09 18:19:28 +00:00
|
|
|
|
if (tem)
|
|
|
|
|
{
|
|
|
|
|
*pcpu = 100.0 * (tem1 + tem2) / tem;
|
|
|
|
|
if (*pcpu > 100)
|
|
|
|
|
*pcpu = 100.0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*pcpu = 0;
|
|
|
|
|
|
|
|
|
|
return 1;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lisp_Object
|
Reorganize implementation of Flist_system_processes and
Fsystem_process_attributes. No functional changes.
* process.c: Don't #include pwd.h, grp.h and limits.h.
(Flist_system_processes): Just call list_system_processes.
(Fsystem_process_attributes): Just call system_process_attributes.
(procfs_list_system_processes, time_from_jiffies)
(ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
(procfs_get_total_memory, procfs_system_process_attributes): Move ...
* sysdep.c: ... here. Include pwd.h, grp.h and limits.h.
(list_system_processes): Rename from
procfs_list_system_processes. Enclose in #ifdef HAVE_PROCFS.
Provide a do nothing implementation.
(system_process_attributes): Rename from
procfs_list_system_processes.
(ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
(procfs_get_total_memory): Enclose in #ifdef GNU_LINUX.
* w32.c (list_system_processes): Rename from
w32_list_system_processes.
(system_process_attributes): Rename from
w32_system_process_attributes.
* s/gnu-linux.h (LISTPROC, PROCATTR): Remove.
* process.h (w32_list_system_processes)
(w32_system_process_attributes): Remove.
(list_system_processes, system_process_attributes): New
prototypes.
* config.nt (LISTPROC, PROCATTR): Remove.
2008-12-19 19:50:35 +00:00
|
|
|
|
system_process_attributes (pid)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
Lisp_Object pid;
|
|
|
|
|
{
|
|
|
|
|
struct gcpro gcpro1, gcpro2, gcpro3;
|
|
|
|
|
Lisp_Object attrs = Qnil;
|
|
|
|
|
Lisp_Object cmd_str, decoded_cmd, tem;
|
|
|
|
|
HANDLE h_snapshot, h_proc;
|
|
|
|
|
DWORD proc_id;
|
2008-08-09 19:05:54 +00:00
|
|
|
|
int found_proc = 0;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
|
2008-08-30 16:46:54 +00:00
|
|
|
|
DWORD ulength = sizeof (uname), dlength = sizeof (domain), needed;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
DWORD glength = sizeof (gname);
|
|
|
|
|
HANDLE token = NULL;
|
|
|
|
|
SID_NAME_USE user_type;
|
2008-08-30 16:46:54 +00:00
|
|
|
|
unsigned char *buf = NULL;
|
|
|
|
|
DWORD blen = 0;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
TOKEN_USER user_token;
|
|
|
|
|
TOKEN_PRIMARY_GROUP group_token;
|
2009-03-21 11:31:50 +00:00
|
|
|
|
unsigned euid;
|
|
|
|
|
unsigned egid;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
DWORD sess;
|
|
|
|
|
PROCESS_MEMORY_COUNTERS mem;
|
|
|
|
|
PROCESS_MEMORY_COUNTERS_EX mem_ex;
|
|
|
|
|
DWORD minrss, maxrss;
|
|
|
|
|
MEMORYSTATUS memst;
|
2008-08-15 12:49:09 +00:00
|
|
|
|
MEMORY_STATUS_EX memstex;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
double totphys = 0.0;
|
2009-01-02 15:08:57 +00:00
|
|
|
|
Lisp_Object ctime, stime, utime, etime, ttime;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
double pcpu;
|
2008-08-30 16:46:54 +00:00
|
|
|
|
BOOL result = FALSE;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
|
|
|
|
|
CHECK_NUMBER_OR_FLOAT (pid);
|
|
|
|
|
proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
|
|
|
|
|
|
|
|
|
|
h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
|
|
|
|
|
|
|
|
|
|
GCPRO3 (attrs, decoded_cmd, tem);
|
|
|
|
|
|
|
|
|
|
if (h_snapshot != INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
PROCESSENTRY32 pe;
|
|
|
|
|
BOOL res;
|
|
|
|
|
|
|
|
|
|
pe.dwSize = sizeof (PROCESSENTRY32);
|
|
|
|
|
for (res = process32_first (h_snapshot, &pe); res;
|
|
|
|
|
res = process32_next (h_snapshot, &pe))
|
|
|
|
|
{
|
|
|
|
|
if (proc_id == pe.th32ProcessID)
|
|
|
|
|
{
|
|
|
|
|
if (proc_id == 0)
|
|
|
|
|
decoded_cmd = build_string ("Idle");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Decode the command name from locale-specific
|
|
|
|
|
encoding. */
|
|
|
|
|
cmd_str = make_unibyte_string (pe.szExeFile,
|
|
|
|
|
strlen (pe.szExeFile));
|
|
|
|
|
decoded_cmd =
|
|
|
|
|
code_convert_string_norecord (cmd_str,
|
|
|
|
|
Vlocale_coding_system, 0);
|
|
|
|
|
}
|
|
|
|
|
attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qppid,
|
|
|
|
|
make_fixnum_or_float (pe.th32ParentProcessID)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qpri, make_number (pe.pcPriClassBase)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qthcount,
|
|
|
|
|
make_fixnum_or_float (pe.cntThreads)),
|
|
|
|
|
attrs);
|
2008-08-09 19:05:54 +00:00
|
|
|
|
found_proc = 1;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle (h_snapshot);
|
|
|
|
|
}
|
|
|
|
|
|
2008-08-09 19:05:54 +00:00
|
|
|
|
if (!found_proc)
|
|
|
|
|
{
|
|
|
|
|
UNGCPRO;
|
|
|
|
|
return Qnil;
|
|
|
|
|
}
|
|
|
|
|
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
|
|
|
|
FALSE, proc_id);
|
|
|
|
|
/* If we were denied a handle to the process, try again after
|
|
|
|
|
enabling the SeDebugPrivilege in our process. */
|
|
|
|
|
if (!h_proc)
|
|
|
|
|
{
|
|
|
|
|
TOKEN_PRIVILEGES priv_current;
|
|
|
|
|
|
|
|
|
|
if (enable_privilege (SE_DEBUG_NAME, TRUE, &priv_current))
|
|
|
|
|
{
|
|
|
|
|
h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
|
|
|
|
FALSE, proc_id);
|
|
|
|
|
restore_privilege (&priv_current);
|
|
|
|
|
revert_to_self ();
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-08-30 16:46:54 +00:00
|
|
|
|
if (h_proc)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
result = open_process_token (h_proc, TOKEN_QUERY, &token);
|
|
|
|
|
if (result)
|
2008-08-15 16:00:19 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
result = get_token_information (token, TokenUser, NULL, 0, &blen);
|
|
|
|
|
if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
|
{
|
|
|
|
|
buf = xmalloc (blen);
|
|
|
|
|
result = get_token_information (token, TokenUser,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
memcpy (&user_token, buf, sizeof (user_token));
|
|
|
|
|
if (!w32_cached_id (user_token.User.Sid, &euid, uname))
|
|
|
|
|
{
|
|
|
|
|
euid = get_rid (user_token.User.Sid);
|
|
|
|
|
result = lookup_account_sid (NULL, user_token.User.Sid,
|
|
|
|
|
uname, &ulength,
|
|
|
|
|
domain, &dlength,
|
|
|
|
|
&user_type);
|
|
|
|
|
if (result)
|
|
|
|
|
w32_add_to_cache (user_token.User.Sid, euid, uname);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy (uname, "unknown");
|
|
|
|
|
result = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ulength = strlen (uname);
|
|
|
|
|
}
|
|
|
|
|
}
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
2008-08-30 16:46:54 +00:00
|
|
|
|
if (result)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
/* Determine a reasonable euid and gid values. */
|
|
|
|
|
if (xstrcasecmp ("administrator", uname) == 0)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
euid = 500; /* well-known Administrator uid */
|
|
|
|
|
egid = 513; /* well-known None gid */
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* Get group id and name. */
|
|
|
|
|
result = get_token_information (token, TokenPrimaryGroup,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
if (!result && GetLastError () == ERROR_INSUFFICIENT_BUFFER)
|
2008-08-15 16:00:19 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
buf = xrealloc (buf, blen = needed);
|
|
|
|
|
result = get_token_information (token, TokenPrimaryGroup,
|
|
|
|
|
(LPVOID)buf, blen, &needed);
|
|
|
|
|
}
|
|
|
|
|
if (result)
|
|
|
|
|
{
|
|
|
|
|
memcpy (&group_token, buf, sizeof (group_token));
|
|
|
|
|
if (!w32_cached_id (group_token.PrimaryGroup, &egid, gname))
|
|
|
|
|
{
|
|
|
|
|
egid = get_rid (group_token.PrimaryGroup);
|
|
|
|
|
dlength = sizeof (domain);
|
|
|
|
|
result =
|
|
|
|
|
lookup_account_sid (NULL, group_token.PrimaryGroup,
|
|
|
|
|
gname, &glength, NULL, &dlength,
|
|
|
|
|
&user_type);
|
|
|
|
|
if (result)
|
|
|
|
|
w32_add_to_cache (group_token.PrimaryGroup,
|
|
|
|
|
egid, gname);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy (gname, "None");
|
|
|
|
|
result = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
glength = strlen (gname);
|
2008-08-15 16:00:19 +00:00
|
|
|
|
}
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-06-29 05:28:54 +00:00
|
|
|
|
xfree (buf);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
2008-08-30 16:46:54 +00:00
|
|
|
|
if (!result)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
2008-08-30 16:46:54 +00:00
|
|
|
|
if (!is_windows_9x ())
|
|
|
|
|
{
|
|
|
|
|
/* We couldn't open the process token, presumably because of
|
|
|
|
|
insufficient access rights. Assume this process is run
|
|
|
|
|
by the system. */
|
|
|
|
|
strcpy (uname, "SYSTEM");
|
|
|
|
|
strcpy (gname, "None");
|
|
|
|
|
euid = 18; /* SYSTEM */
|
|
|
|
|
egid = 513; /* None */
|
|
|
|
|
glength = strlen (gname);
|
|
|
|
|
ulength = strlen (uname);
|
|
|
|
|
}
|
|
|
|
|
/* If we are running under Windows 9X, where security calls are
|
|
|
|
|
not supported, we assume all processes are run by the current
|
|
|
|
|
user. */
|
|
|
|
|
else if (GetUserName (uname, &ulength))
|
|
|
|
|
{
|
|
|
|
|
if (xstrcasecmp ("administrator", uname) == 0)
|
|
|
|
|
euid = 0;
|
|
|
|
|
else
|
|
|
|
|
euid = 123;
|
|
|
|
|
egid = euid;
|
|
|
|
|
strcpy (gname, "None");
|
|
|
|
|
glength = strlen (gname);
|
|
|
|
|
ulength = strlen (uname);
|
|
|
|
|
}
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
else
|
2008-08-30 16:46:54 +00:00
|
|
|
|
{
|
|
|
|
|
euid = 123;
|
|
|
|
|
egid = 123;
|
|
|
|
|
strcpy (uname, "administrator");
|
|
|
|
|
ulength = strlen (uname);
|
|
|
|
|
strcpy (gname, "None");
|
|
|
|
|
glength = strlen (gname);
|
|
|
|
|
}
|
|
|
|
|
if (token)
|
|
|
|
|
CloseHandle (token);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (euid)), attrs);
|
|
|
|
|
tem = make_unibyte_string (uname, ulength);
|
|
|
|
|
attrs = Fcons (Fcons (Quser,
|
|
|
|
|
code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (egid)), attrs);
|
|
|
|
|
tem = make_unibyte_string (gname, glength);
|
|
|
|
|
attrs = Fcons (Fcons (Qgroup,
|
|
|
|
|
code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
|
|
|
|
|
attrs);
|
|
|
|
|
|
|
|
|
|
if (global_memory_status_ex (&memstex))
|
2008-08-15 17:36:48 +00:00
|
|
|
|
#if __GNUC__ || (defined (_MSC_VER) && _MSC_VER >= 1300)
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
totphys = memstex.ullTotalPhys / 1024.0;
|
2008-08-15 17:36:48 +00:00
|
|
|
|
#else
|
|
|
|
|
/* Visual Studio 6 cannot convert an unsigned __int64 type to
|
|
|
|
|
double, so we need to do this for it... */
|
|
|
|
|
{
|
|
|
|
|
DWORD tot_hi = memstex.ullTotalPhys >> 32;
|
|
|
|
|
DWORD tot_md = (memstex.ullTotalPhys & 0x00000000ffffffff) >> 10;
|
|
|
|
|
DWORD tot_lo = memstex.ullTotalPhys % 1024;
|
|
|
|
|
|
|
|
|
|
totphys = tot_hi * 4194304.0 + tot_md + tot_lo / 1024.0;
|
|
|
|
|
}
|
|
|
|
|
#endif /* __GNUC__ || _MSC_VER >= 1300 */
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
else if (global_memory_status (&memst))
|
|
|
|
|
totphys = memst.dwTotalPhys / 1024.0;
|
|
|
|
|
|
|
|
|
|
if (h_proc
|
|
|
|
|
&& get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
|
|
|
|
|
sizeof (mem_ex)))
|
|
|
|
|
{
|
|
|
|
|
DWORD rss = mem_ex.WorkingSetSize / 1024;
|
|
|
|
|
|
|
|
|
|
attrs = Fcons (Fcons (Qmajflt,
|
|
|
|
|
make_fixnum_or_float (mem_ex.PageFaultCount)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qvsize,
|
|
|
|
|
make_fixnum_or_float (mem_ex.PrivateUsage / 1024)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
|
|
|
|
|
if (totphys)
|
|
|
|
|
attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
|
|
|
|
|
}
|
|
|
|
|
else if (h_proc
|
|
|
|
|
&& get_process_memory_info (h_proc, &mem, sizeof (mem)))
|
|
|
|
|
{
|
|
|
|
|
DWORD rss = mem_ex.WorkingSetSize / 1024;
|
|
|
|
|
|
|
|
|
|
attrs = Fcons (Fcons (Qmajflt,
|
|
|
|
|
make_fixnum_or_float (mem.PageFaultCount)),
|
|
|
|
|
attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
|
|
|
|
|
if (totphys)
|
|
|
|
|
attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
|
|
|
|
|
}
|
|
|
|
|
else if (h_proc
|
|
|
|
|
&& get_process_working_set_size (h_proc, &minrss, &maxrss))
|
|
|
|
|
{
|
|
|
|
|
DWORD rss = maxrss / 1024;
|
|
|
|
|
|
|
|
|
|
attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (maxrss / 1024)), attrs);
|
|
|
|
|
if (totphys)
|
|
|
|
|
attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-02 15:08:57 +00:00
|
|
|
|
if (process_times (h_proc, &ctime, &etime, &stime, &utime, &ttime, &pcpu))
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
{
|
|
|
|
|
attrs = Fcons (Fcons (Qutime, utime), attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qstime, stime), attrs);
|
2009-01-02 15:08:57 +00:00
|
|
|
|
attrs = Fcons (Fcons (Qtime, ttime), attrs);
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
attrs = Fcons (Fcons (Qstart, ctime), attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qetime, etime), attrs);
|
|
|
|
|
attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* FIXME: Retrieve command line by walking the PEB of the process. */
|
|
|
|
|
|
|
|
|
|
if (h_proc)
|
|
|
|
|
CloseHandle (h_proc);
|
|
|
|
|
UNGCPRO;
|
|
|
|
|
return attrs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS
|
|
|
|
|
|
|
|
|
|
/* Wrappers for winsock functions to map between our file descriptors
|
|
|
|
|
and winsock's handles; also set h_errno for convenience.
|
|
|
|
|
|
|
|
|
|
To allow Emacs to run on systems which don't have winsock support
|
|
|
|
|
installed, we dynamically link to winsock on startup if present, and
|
|
|
|
|
otherwise provide the minimum necessary functionality
|
|
|
|
|
(eg. gethostname). */
|
|
|
|
|
|
|
|
|
|
/* function pointers for relevant socket functions */
|
|
|
|
|
int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
|
|
|
|
|
void (PASCAL *pfn_WSASetLastError) (int iError);
|
|
|
|
|
int (PASCAL *pfn_WSAGetLastError) (void);
|
2006-07-14 09:29:32 +00:00
|
|
|
|
int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
|
2006-07-14 14:18:40 +00:00
|
|
|
|
HANDLE (PASCAL *pfn_WSACreateEvent) (void);
|
|
|
|
|
int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int (PASCAL *pfn_socket) (int af, int type, int protocol);
|
|
|
|
|
int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
|
|
|
|
|
int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
|
|
|
|
|
int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
|
|
|
|
|
int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
|
|
|
|
|
int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
|
|
|
|
|
int (PASCAL *pfn_closesocket) (SOCKET s);
|
|
|
|
|
int (PASCAL *pfn_shutdown) (SOCKET s, int how);
|
|
|
|
|
int (PASCAL *pfn_WSACleanup) (void);
|
|
|
|
|
|
|
|
|
|
u_short (PASCAL *pfn_htons) (u_short hostshort);
|
|
|
|
|
u_short (PASCAL *pfn_ntohs) (u_short netshort);
|
|
|
|
|
unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
|
|
|
|
|
int (PASCAL *pfn_gethostname) (char * name, int namelen);
|
|
|
|
|
struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
|
|
|
|
|
struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
|
2002-05-03 20:40:03 +00:00
|
|
|
|
int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
|
2002-03-20 20:38:44 +00:00
|
|
|
|
int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
|
|
|
|
|
const char * optval, int optlen);
|
|
|
|
|
int (PASCAL *pfn_listen) (SOCKET s, int backlog);
|
|
|
|
|
int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
|
|
|
|
|
int * namelen);
|
|
|
|
|
SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
|
|
|
|
|
int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
|
|
|
|
|
struct sockaddr * from, int * fromlen);
|
|
|
|
|
int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
|
|
|
|
|
const struct sockaddr * to, int tolen);
|
|
|
|
|
|
1996-06-06 17:07:00 +00:00
|
|
|
|
/* SetHandleInformation is only needed to make sockets non-inheritable. */
|
|
|
|
|
BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
|
|
|
|
|
#ifndef HANDLE_FLAG_INHERIT
|
|
|
|
|
#define HANDLE_FLAG_INHERIT 1
|
|
|
|
|
#endif
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
HANDLE winsock_lib;
|
|
|
|
|
static int winsock_inuse;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
BOOL
|
1996-05-03 18:32:52 +00:00
|
|
|
|
term_winsock (void)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib != NULL && winsock_inuse == 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
/* Not sure what would cause WSAENETDOWN, or even if it can happen
|
|
|
|
|
after WSAStartup returns successfully, but it seems reasonable
|
|
|
|
|
to allow unloading winsock anyway in that case. */
|
|
|
|
|
if (pfn_WSACleanup () == 0 ||
|
|
|
|
|
pfn_WSAGetLastError () == WSAENETDOWN)
|
|
|
|
|
{
|
|
|
|
|
if (FreeLibrary (winsock_lib))
|
|
|
|
|
winsock_lib = NULL;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
return FALSE;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
BOOL
|
|
|
|
|
init_winsock (int load_now)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
WSADATA winsockData;
|
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib != NULL)
|
|
|
|
|
return TRUE;
|
1996-06-06 17:07:00 +00:00
|
|
|
|
|
|
|
|
|
pfn_SetHandleInformation = NULL;
|
|
|
|
|
pfn_SetHandleInformation
|
|
|
|
|
= (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
|
|
|
|
|
"SetHandleInformation");
|
|
|
|
|
|
2006-07-14 14:18:40 +00:00
|
|
|
|
winsock_lib = LoadLibrary ("Ws2_32.dll");
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (winsock_lib != NULL)
|
|
|
|
|
{
|
|
|
|
|
/* dynamically link to socket functions */
|
|
|
|
|
|
|
|
|
|
#define LOAD_PROC(fn) \
|
|
|
|
|
if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
LOAD_PROC( WSAStartup );
|
|
|
|
|
LOAD_PROC( WSASetLastError );
|
|
|
|
|
LOAD_PROC( WSAGetLastError );
|
2006-07-14 09:29:32 +00:00
|
|
|
|
LOAD_PROC( WSAEventSelect );
|
2006-07-14 14:18:40 +00:00
|
|
|
|
LOAD_PROC( WSACreateEvent );
|
|
|
|
|
LOAD_PROC( WSACloseEvent );
|
1996-05-03 18:32:52 +00:00
|
|
|
|
LOAD_PROC( socket );
|
|
|
|
|
LOAD_PROC( bind );
|
|
|
|
|
LOAD_PROC( connect );
|
|
|
|
|
LOAD_PROC( ioctlsocket );
|
|
|
|
|
LOAD_PROC( recv );
|
|
|
|
|
LOAD_PROC( send );
|
|
|
|
|
LOAD_PROC( closesocket );
|
|
|
|
|
LOAD_PROC( shutdown );
|
|
|
|
|
LOAD_PROC( htons );
|
|
|
|
|
LOAD_PROC( ntohs );
|
|
|
|
|
LOAD_PROC( inet_addr );
|
|
|
|
|
LOAD_PROC( gethostname );
|
|
|
|
|
LOAD_PROC( gethostbyname );
|
|
|
|
|
LOAD_PROC( getservbyname );
|
2002-05-03 20:40:03 +00:00
|
|
|
|
LOAD_PROC( getpeername );
|
1996-05-03 18:32:52 +00:00
|
|
|
|
LOAD_PROC( WSACleanup );
|
2002-03-20 20:38:44 +00:00
|
|
|
|
LOAD_PROC( setsockopt );
|
|
|
|
|
LOAD_PROC( listen );
|
|
|
|
|
LOAD_PROC( getsockname );
|
|
|
|
|
LOAD_PROC( accept );
|
|
|
|
|
LOAD_PROC( recvfrom );
|
|
|
|
|
LOAD_PROC( sendto );
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
#undef LOAD_PROC
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* specify version 1.1 of winsock */
|
|
|
|
|
if (pfn_WSAStartup (0x101, &winsockData) == 0)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsockData.wVersion != 0x101)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
if (!load_now)
|
|
|
|
|
{
|
|
|
|
|
/* Report that winsock exists and is usable, but leave
|
|
|
|
|
socket functions disabled. I am assuming that calling
|
|
|
|
|
WSAStartup does not require any network interaction,
|
|
|
|
|
and in particular does not cause or require a dial-up
|
|
|
|
|
connection to be established. */
|
|
|
|
|
|
|
|
|
|
pfn_WSACleanup ();
|
|
|
|
|
FreeLibrary (winsock_lib);
|
|
|
|
|
winsock_lib = NULL;
|
|
|
|
|
}
|
|
|
|
|
winsock_inuse = 0;
|
|
|
|
|
return TRUE;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
FreeLibrary (winsock_lib);
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
winsock_lib = NULL;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
|
|
|
|
|
return FALSE;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int h_errno = 0;
|
|
|
|
|
|
2008-07-01 03:04:08 +00:00
|
|
|
|
/* function to set h_errno for compatibility; map winsock error codes to
|
1996-05-03 18:32:52 +00:00
|
|
|
|
normal system codes where they overlap (non-overlapping definitions
|
|
|
|
|
are already in <sys/socket.h> */
|
2006-12-27 21:55:59 +00:00
|
|
|
|
static void
|
|
|
|
|
set_errno ()
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
h_errno = EINVAL;
|
|
|
|
|
else
|
|
|
|
|
h_errno = pfn_WSAGetLastError ();
|
|
|
|
|
|
|
|
|
|
switch (h_errno)
|
|
|
|
|
{
|
|
|
|
|
case WSAEACCES: h_errno = EACCES; break;
|
|
|
|
|
case WSAEBADF: h_errno = EBADF; break;
|
|
|
|
|
case WSAEFAULT: h_errno = EFAULT; break;
|
|
|
|
|
case WSAEINTR: h_errno = EINTR; break;
|
|
|
|
|
case WSAEINVAL: h_errno = EINVAL; break;
|
|
|
|
|
case WSAEMFILE: h_errno = EMFILE; break;
|
|
|
|
|
case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
|
|
|
|
|
case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
|
|
|
|
|
}
|
|
|
|
|
errno = h_errno;
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-27 21:55:59 +00:00
|
|
|
|
static void
|
|
|
|
|
check_errno ()
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (h_errno == 0 && winsock_lib != NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
pfn_WSASetLastError (0);
|
|
|
|
|
}
|
|
|
|
|
|
1999-06-16 20:00:19 +00:00
|
|
|
|
/* Extend strerror to handle the winsock-specific error codes. */
|
|
|
|
|
struct {
|
|
|
|
|
int errnum;
|
|
|
|
|
char * msg;
|
|
|
|
|
} _wsa_errlist[] = {
|
|
|
|
|
WSAEINTR , "Interrupted function call",
|
|
|
|
|
WSAEBADF , "Bad file descriptor",
|
|
|
|
|
WSAEACCES , "Permission denied",
|
|
|
|
|
WSAEFAULT , "Bad address",
|
|
|
|
|
WSAEINVAL , "Invalid argument",
|
|
|
|
|
WSAEMFILE , "Too many open files",
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1999-06-16 20:00:19 +00:00
|
|
|
|
WSAEWOULDBLOCK , "Resource temporarily unavailable",
|
|
|
|
|
WSAEINPROGRESS , "Operation now in progress",
|
|
|
|
|
WSAEALREADY , "Operation already in progress",
|
|
|
|
|
WSAENOTSOCK , "Socket operation on non-socket",
|
|
|
|
|
WSAEDESTADDRREQ , "Destination address required",
|
|
|
|
|
WSAEMSGSIZE , "Message too long",
|
|
|
|
|
WSAEPROTOTYPE , "Protocol wrong type for socket",
|
|
|
|
|
WSAENOPROTOOPT , "Bad protocol option",
|
|
|
|
|
WSAEPROTONOSUPPORT , "Protocol not supported",
|
|
|
|
|
WSAESOCKTNOSUPPORT , "Socket type not supported",
|
|
|
|
|
WSAEOPNOTSUPP , "Operation not supported",
|
|
|
|
|
WSAEPFNOSUPPORT , "Protocol family not supported",
|
|
|
|
|
WSAEAFNOSUPPORT , "Address family not supported by protocol family",
|
|
|
|
|
WSAEADDRINUSE , "Address already in use",
|
|
|
|
|
WSAEADDRNOTAVAIL , "Cannot assign requested address",
|
|
|
|
|
WSAENETDOWN , "Network is down",
|
|
|
|
|
WSAENETUNREACH , "Network is unreachable",
|
|
|
|
|
WSAENETRESET , "Network dropped connection on reset",
|
|
|
|
|
WSAECONNABORTED , "Software caused connection abort",
|
|
|
|
|
WSAECONNRESET , "Connection reset by peer",
|
|
|
|
|
WSAENOBUFS , "No buffer space available",
|
|
|
|
|
WSAEISCONN , "Socket is already connected",
|
|
|
|
|
WSAENOTCONN , "Socket is not connected",
|
|
|
|
|
WSAESHUTDOWN , "Cannot send after socket shutdown",
|
|
|
|
|
WSAETOOMANYREFS , "Too many references", /* not sure */
|
|
|
|
|
WSAETIMEDOUT , "Connection timed out",
|
|
|
|
|
WSAECONNREFUSED , "Connection refused",
|
|
|
|
|
WSAELOOP , "Network loop", /* not sure */
|
|
|
|
|
WSAENAMETOOLONG , "Name is too long",
|
|
|
|
|
WSAEHOSTDOWN , "Host is down",
|
|
|
|
|
WSAEHOSTUNREACH , "No route to host",
|
|
|
|
|
WSAENOTEMPTY , "Buffer not empty", /* not sure */
|
|
|
|
|
WSAEPROCLIM , "Too many processes",
|
|
|
|
|
WSAEUSERS , "Too many users", /* not sure */
|
|
|
|
|
WSAEDQUOT , "Double quote in host name", /* really not sure */
|
|
|
|
|
WSAESTALE , "Data is stale", /* not sure */
|
|
|
|
|
WSAEREMOTE , "Remote error", /* not sure */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1999-06-16 20:00:19 +00:00
|
|
|
|
WSASYSNOTREADY , "Network subsystem is unavailable",
|
|
|
|
|
WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
|
|
|
|
|
WSANOTINITIALISED , "Winsock not initialized successfully",
|
|
|
|
|
WSAEDISCON , "Graceful shutdown in progress",
|
|
|
|
|
#ifdef WSAENOMORE
|
|
|
|
|
WSAENOMORE , "No more operations allowed", /* not sure */
|
|
|
|
|
WSAECANCELLED , "Operation cancelled", /* not sure */
|
|
|
|
|
WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
|
|
|
|
|
WSAEINVALIDPROVIDER , "Invalid service provider version number",
|
|
|
|
|
WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
|
2007-06-20 08:31:09 +00:00
|
|
|
|
WSASYSCALLFAILURE , "System call failure",
|
1999-06-16 20:00:19 +00:00
|
|
|
|
WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
|
|
|
|
|
WSATYPE_NOT_FOUND , "Class type not found",
|
|
|
|
|
WSA_E_NO_MORE , "No more resources available", /* really not sure */
|
|
|
|
|
WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
|
|
|
|
|
WSAEREFUSED , "Operation refused", /* not sure */
|
|
|
|
|
#endif
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1999-06-16 20:00:19 +00:00
|
|
|
|
WSAHOST_NOT_FOUND , "Host not found",
|
|
|
|
|
WSATRY_AGAIN , "Authoritative host not found during name lookup",
|
|
|
|
|
WSANO_RECOVERY , "Non-recoverable error during name lookup",
|
|
|
|
|
WSANO_DATA , "Valid name, no data record of requested type",
|
|
|
|
|
|
|
|
|
|
-1, NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
sys_strerror(int error_no)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
static char unknown_msg[40];
|
|
|
|
|
|
2000-08-22 22:49:27 +00:00
|
|
|
|
if (error_no >= 0 && error_no < sys_nerr)
|
|
|
|
|
return sys_errlist[error_no];
|
1999-06-16 20:00:19 +00:00
|
|
|
|
|
|
|
|
|
for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
|
|
|
|
|
if (_wsa_errlist[i].errnum == error_no)
|
|
|
|
|
return _wsa_errlist[i].msg;
|
|
|
|
|
|
|
|
|
|
sprintf(unknown_msg, "Unidentified error: %d", error_no);
|
|
|
|
|
return unknown_msg;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* [andrewi 3-May-96] I've had conflicting results using both methods,
|
|
|
|
|
but I believe the method of keeping the socket handle separate (and
|
|
|
|
|
insuring it is not inheritable) is the correct one. */
|
|
|
|
|
|
|
|
|
|
//#define SOCK_REPLACE_HANDLE
|
|
|
|
|
|
|
|
|
|
#ifdef SOCK_REPLACE_HANDLE
|
|
|
|
|
#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
|
|
|
|
|
#else
|
|
|
|
|
#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
int socket_to_fd (SOCKET s);
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int
|
|
|
|
|
sys_socket(int af, int type, int protocol)
|
|
|
|
|
{
|
2002-03-20 20:38:44 +00:00
|
|
|
|
SOCKET s;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return INVALID_SOCKET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
|
|
|
|
|
/* call the real socket function */
|
2002-03-20 20:38:44 +00:00
|
|
|
|
s = pfn_socket (af, type, protocol);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (s != INVALID_SOCKET)
|
2002-03-20 20:38:44 +00:00
|
|
|
|
return socket_to_fd (s);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
set_errno ();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Convert a SOCKET to a file descriptor. */
|
|
|
|
|
int
|
|
|
|
|
socket_to_fd (SOCKET s)
|
|
|
|
|
{
|
|
|
|
|
int fd;
|
|
|
|
|
child_process * cp;
|
|
|
|
|
|
|
|
|
|
/* Although under NT 3.5 _open_osfhandle will accept a socket
|
|
|
|
|
handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
|
|
|
|
|
that does not work under NT 3.1. However, we can get the same
|
|
|
|
|
effect by using a backdoor function to replace an existing
|
|
|
|
|
descriptor handle with the one we want. */
|
|
|
|
|
|
|
|
|
|
/* allocate a file descriptor (with appropriate flags) */
|
|
|
|
|
fd = _open ("NUL:", _O_RDWR);
|
|
|
|
|
if (fd >= 0)
|
|
|
|
|
{
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef SOCK_REPLACE_HANDLE
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* now replace handle to NUL with our socket handle */
|
|
|
|
|
CloseHandle ((HANDLE) _get_osfhandle (fd));
|
|
|
|
|
_free_osfhnd (fd);
|
|
|
|
|
_set_osfhnd (fd, s);
|
|
|
|
|
/* setmode (fd, _O_BINARY); */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#else
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* Make a non-inheritable copy of the socket handle. Note
|
|
|
|
|
that it is possible that sockets aren't actually kernel
|
|
|
|
|
handles, which appears to be the case on Windows 9x when
|
|
|
|
|
the MS Proxy winsock client is installed. */
|
|
|
|
|
{
|
|
|
|
|
/* Apparently there is a bug in NT 3.51 with some service
|
|
|
|
|
packs, which prevents using DuplicateHandle to make a
|
|
|
|
|
socket handle non-inheritable (causes WSACleanup to
|
|
|
|
|
hang). The work-around is to use SetHandleInformation
|
|
|
|
|
instead if it is available and implemented. */
|
|
|
|
|
if (pfn_SetHandleInformation)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2002-03-20 20:38:44 +00:00
|
|
|
|
pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
HANDLE parent = GetCurrentProcess ();
|
|
|
|
|
HANDLE new_s = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
|
|
if (DuplicateHandle (parent,
|
|
|
|
|
(HANDLE) s,
|
|
|
|
|
parent,
|
|
|
|
|
&new_s,
|
|
|
|
|
0,
|
|
|
|
|
FALSE,
|
|
|
|
|
DUPLICATE_SAME_ACCESS))
|
1996-06-06 17:07:00 +00:00
|
|
|
|
{
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* It is possible that DuplicateHandle succeeds even
|
|
|
|
|
though the socket wasn't really a kernel handle,
|
|
|
|
|
because a real handle has the same value. So
|
|
|
|
|
test whether the new handle really is a socket. */
|
|
|
|
|
long nonblocking = 0;
|
|
|
|
|
if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
|
2000-07-05 16:00:13 +00:00
|
|
|
|
{
|
2002-03-20 20:38:44 +00:00
|
|
|
|
pfn_closesocket (s);
|
|
|
|
|
s = (SOCKET) new_s;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
CloseHandle (new_s);
|
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
2002-03-20 20:38:44 +00:00
|
|
|
|
}
|
|
|
|
|
fd_info[fd].hnd = (HANDLE) s;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* set our own internal flags */
|
|
|
|
|
fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
cp = new_child ();
|
|
|
|
|
if (cp)
|
|
|
|
|
{
|
|
|
|
|
cp->fd = fd;
|
|
|
|
|
cp->status = STATUS_READ_ACKNOWLEDGED;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* attach child_process to fd_info */
|
|
|
|
|
if (fd_info[ fd ].cp != NULL)
|
|
|
|
|
{
|
|
|
|
|
DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
|
|
|
|
|
abort ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
fd_info[ fd ].cp = cp;
|
|
|
|
|
|
|
|
|
|
/* success! */
|
|
|
|
|
winsock_inuse++; /* count open sockets */
|
|
|
|
|
return fd;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-20 20:38:44 +00:00
|
|
|
|
/* clean up */
|
|
|
|
|
_close (fd);
|
|
|
|
|
}
|
|
|
|
|
pfn_closesocket (s);
|
|
|
|
|
h_errno = EMFILE;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_bind (int s, const struct sockaddr * addr, int namelen)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_connect (int s, const struct sockaddr * name, int namelen)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u_short
|
|
|
|
|
sys_htons (u_short hostshort)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
return (winsock_lib != NULL) ?
|
1996-05-03 18:32:52 +00:00
|
|
|
|
pfn_htons (hostshort) : hostshort;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
u_short
|
|
|
|
|
sys_ntohs (u_short netshort)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
return (winsock_lib != NULL) ?
|
1996-05-03 18:32:52 +00:00
|
|
|
|
pfn_ntohs (netshort) : netshort;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned long
|
|
|
|
|
sys_inet_addr (const char * cp)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
return (winsock_lib != NULL) ?
|
1996-05-03 18:32:52 +00:00
|
|
|
|
pfn_inet_addr (cp) : INADDR_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_gethostname (char * name, int namelen)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib != NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
return pfn_gethostname (name, namelen);
|
|
|
|
|
|
|
|
|
|
if (namelen > MAX_COMPUTERNAME_LENGTH)
|
2000-08-22 22:49:27 +00:00
|
|
|
|
return !GetComputerName (name, (DWORD *)&namelen);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
h_errno = EFAULT;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct hostent *
|
|
|
|
|
sys_gethostbyname(const char * name)
|
|
|
|
|
{
|
|
|
|
|
struct hostent * host;
|
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
host = pfn_gethostbyname (name);
|
|
|
|
|
if (!host)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return host;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct servent *
|
|
|
|
|
sys_getservbyname(const char * name, const char * proto)
|
|
|
|
|
{
|
|
|
|
|
struct servent * serv;
|
|
|
|
|
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
serv = pfn_getservbyname (name, proto);
|
|
|
|
|
if (!serv)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return serv;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-03 20:40:03 +00:00
|
|
|
|
int
|
|
|
|
|
sys_getpeername (int s, struct sockaddr *addr, int * namelen)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1997-07-10 20:10:09 +00:00
|
|
|
|
int
|
|
|
|
|
sys_shutdown (int s, int how)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_shutdown (SOCK_HANDLE (s), how);
|
2002-03-20 20:38:44 +00:00
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2005-06-05 19:13:37 +00:00
|
|
|
|
sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
|
2002-03-20 20:38:44 +00:00
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
|
2005-06-05 19:13:37 +00:00
|
|
|
|
(const char *)optval, optlen);
|
2002-03-20 20:38:44 +00:00
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
return SOCKET_ERROR;
|
2002-03-20 20:38:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_listen (int s, int backlog)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_listen (SOCK_HANDLE (s), backlog);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
2006-07-14 09:29:32 +00:00
|
|
|
|
else
|
2006-07-14 14:18:40 +00:00
|
|
|
|
fd_info[s].flags |= FILE_LISTEN;
|
2002-03-20 20:38:44 +00:00
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
return SOCKET_ERROR;
|
2002-03-20 20:38:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_getsockname (int s, struct sockaddr * name, int * namelen)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
return SOCKET_ERROR;
|
2002-03-20 20:38:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_accept (int s, struct sockaddr * addr, int * addrlen)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
2006-07-14 09:29:32 +00:00
|
|
|
|
if (fd_info[s].flags & FILE_LISTEN)
|
2002-03-20 20:38:44 +00:00
|
|
|
|
{
|
2002-04-08 16:45:43 +00:00
|
|
|
|
SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
|
2006-07-14 14:18:40 +00:00
|
|
|
|
int fd = -1;
|
|
|
|
|
if (t == INVALID_SOCKET)
|
|
|
|
|
set_errno ();
|
|
|
|
|
else
|
|
|
|
|
fd = socket_to_fd (t);
|
2002-03-20 20:38:44 +00:00
|
|
|
|
|
2006-07-14 14:18:40 +00:00
|
|
|
|
fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
|
|
|
|
|
ResetEvent (fd_info[s].cp->char_avail);
|
|
|
|
|
return fd;
|
2002-03-20 20:38:44 +00:00
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_recvfrom (int s, char * buf, int len, int flags,
|
|
|
|
|
struct sockaddr * from, int * fromlen)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_sendto (int s, const char * buf, int len, int flags,
|
|
|
|
|
const struct sockaddr * to, int tolen)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
|
1997-07-10 20:10:09 +00:00
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno ();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-03 20:40:03 +00:00
|
|
|
|
/* Windows does not have an fcntl function. Provide an implementation
|
|
|
|
|
solely for making sockets non-blocking. */
|
|
|
|
|
int
|
|
|
|
|
fcntl (int s, int cmd, int options)
|
|
|
|
|
{
|
|
|
|
|
if (winsock_lib == NULL)
|
|
|
|
|
{
|
|
|
|
|
h_errno = ENETDOWN;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check_errno ();
|
|
|
|
|
if (fd_info[s].flags & FILE_SOCKET)
|
|
|
|
|
{
|
|
|
|
|
if (cmd == F_SETFL && options == O_NDELAY)
|
|
|
|
|
{
|
|
|
|
|
unsigned long nblock = 1;
|
|
|
|
|
int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
|
|
|
|
|
if (rc == SOCKET_ERROR)
|
|
|
|
|
set_errno();
|
|
|
|
|
/* Keep track of the fact that we set this to non-blocking. */
|
|
|
|
|
fd_info[s].flags |= FILE_NDELAY;
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
h_errno = EINVAL;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
h_errno = ENOTSOCK;
|
|
|
|
|
return SOCKET_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif /* HAVE_SOCKETS */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Shadow main io functions: we need to handle pipes and sockets more
|
|
|
|
|
intelligently, and implement non-blocking mode as well. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_close (int fd)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (fd < 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (fd < MAXDESC && fd_info[fd].cp)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
child_process * cp = fd_info[fd].cp;
|
|
|
|
|
|
|
|
|
|
fd_info[fd].cp = NULL;
|
|
|
|
|
|
|
|
|
|
if (CHILD_ACTIVE (cp))
|
|
|
|
|
{
|
|
|
|
|
/* if last descriptor to active child_process then cleanup */
|
|
|
|
|
int i;
|
|
|
|
|
for (i = 0; i < MAXDESC; i++)
|
|
|
|
|
{
|
|
|
|
|
if (i == fd)
|
|
|
|
|
continue;
|
|
|
|
|
if (fd_info[i].cp == cp)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (i == MAXDESC)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (fd_info[fd].flags & FILE_SOCKET)
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
#ifndef SOCK_REPLACE_HANDLE
|
|
|
|
|
if (winsock_lib == NULL) abort ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
pfn_shutdown (SOCK_HANDLE (fd), 2);
|
|
|
|
|
rc = pfn_closesocket (SOCK_HANDLE (fd));
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
#endif
|
|
|
|
|
winsock_inuse--; /* count open sockets */
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
delete_child (cp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Note that sockets do not need special treatment here (at least on
|
1997-01-20 00:38:22 +00:00
|
|
|
|
NT and Windows 95 using the standard tcp/ip stacks) - it appears that
|
1996-05-03 18:32:52 +00:00
|
|
|
|
closesocket is equivalent to CloseHandle, which is to be expected
|
|
|
|
|
because socket handles are fully fledged kernel handles. */
|
|
|
|
|
rc = _close (fd);
|
|
|
|
|
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (rc == 0 && fd < MAXDESC)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
fd_info[fd].flags = 0;
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_dup (int fd)
|
|
|
|
|
{
|
|
|
|
|
int new_fd;
|
|
|
|
|
|
|
|
|
|
new_fd = _dup (fd);
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (new_fd >= 0 && new_fd < MAXDESC)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
/* duplicate our internal info as well */
|
|
|
|
|
fd_info[new_fd] = fd_info[fd];
|
|
|
|
|
}
|
|
|
|
|
return new_fd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
sys_dup2 (int src, int dst)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
if (dst < 0 || dst >= MAXDESC)
|
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* make sure we close the destination first if it's a pipe or socket */
|
|
|
|
|
if (src != dst && fd_info[dst].flags != 0)
|
|
|
|
|
sys_close (dst);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
rc = _dup2 (src, dst);
|
|
|
|
|
if (rc == 0)
|
|
|
|
|
{
|
|
|
|
|
/* duplicate our internal info as well */
|
|
|
|
|
fd_info[dst] = fd_info[src];
|
|
|
|
|
}
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unix pipe() has only one arg */
|
|
|
|
|
int
|
|
|
|
|
sys_pipe (int * phandles)
|
|
|
|
|
{
|
|
|
|
|
int rc;
|
|
|
|
|
unsigned flags;
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* make pipe handles non-inheritable; when we spawn a child, we
|
|
|
|
|
replace the relevant handle with an inheritable one. Also put
|
|
|
|
|
pipes into binary mode; we will do text mode translation ourselves
|
|
|
|
|
if required. */
|
|
|
|
|
rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (rc == 0)
|
|
|
|
|
{
|
2003-08-27 22:57:54 +00:00
|
|
|
|
/* Protect against overflow, since Windows can open more handles than
|
|
|
|
|
our fd_info array has room for. */
|
|
|
|
|
if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
|
|
|
|
|
{
|
|
|
|
|
_close (phandles[0]);
|
|
|
|
|
_close (phandles[1]);
|
|
|
|
|
rc = -1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
flags = FILE_PIPE | FILE_READ | FILE_BINARY;
|
|
|
|
|
fd_info[phandles[0]].flags = flags;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2003-08-27 22:57:54 +00:00
|
|
|
|
flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
|
|
|
|
|
fd_info[phandles[1]].flags = flags;
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-17 21:45:30 +00:00
|
|
|
|
/* From ntproc.c */
|
2004-05-17 21:05:58 +00:00
|
|
|
|
extern int w32_pipe_read_delay;
|
1996-05-17 21:45:30 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* Function to do blocking read of one byte, needed to implement
|
|
|
|
|
select. It is only allowed on sockets and pipes. */
|
|
|
|
|
int
|
|
|
|
|
_sys_read_ahead (int fd)
|
|
|
|
|
{
|
|
|
|
|
child_process * cp;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
if (fd < 0 || fd >= MAXDESC)
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
|
|
|
|
|
cp = fd_info[fd].cp;
|
|
|
|
|
|
|
|
|
|
if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
if ((fd_info[fd].flags & (FILE_PIPE | FILE_SERIAL | FILE_SOCKET)) == 0
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|| (fd_info[fd].flags & FILE_READ) == 0)
|
|
|
|
|
{
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe, serial port, or socket!\n", fd));
|
1996-05-03 18:32:52 +00:00
|
|
|
|
abort ();
|
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
cp->status = STATUS_READ_IN_PROGRESS;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (fd_info[fd].flags & FILE_PIPE)
|
1996-05-17 21:45:30 +00:00
|
|
|
|
{
|
|
|
|
|
rc = _read (fd, &cp->chr, sizeof (char));
|
|
|
|
|
|
|
|
|
|
/* Give subprocess time to buffer some more output for us before
|
1997-01-20 00:38:22 +00:00
|
|
|
|
reporting that input is available; we need this because Windows 95
|
1996-05-17 21:45:30 +00:00
|
|
|
|
connects DOS programs to pipes by making the pipe appear to be
|
|
|
|
|
the normal console stdout - as a result most DOS programs will
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
write to stdout without buffering, ie. one character at a
|
1996-11-19 04:59:23 +00:00
|
|
|
|
time. Even some W32 programs do this - "dir" in a command
|
1996-05-17 21:45:30 +00:00
|
|
|
|
shell on NT is very slow if we don't do this. */
|
|
|
|
|
if (rc > 0)
|
|
|
|
|
{
|
2004-05-17 21:05:58 +00:00
|
|
|
|
int wait = w32_pipe_read_delay;
|
1996-05-17 21:45:30 +00:00
|
|
|
|
|
|
|
|
|
if (wait > 0)
|
|
|
|
|
Sleep (wait);
|
|
|
|
|
else if (wait < 0)
|
|
|
|
|
while (++wait <= 0)
|
|
|
|
|
/* Yield remainder of our time slice, effectively giving a
|
|
|
|
|
temporary priority boost to the child process. */
|
|
|
|
|
Sleep (0);
|
|
|
|
|
}
|
|
|
|
|
}
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
else if (fd_info[fd].flags & FILE_SERIAL)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hnd = fd_info[fd].hnd;
|
|
|
|
|
OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
|
|
|
|
|
COMMTIMEOUTS ct;
|
|
|
|
|
|
|
|
|
|
/* Configure timeouts for blocking read. */
|
|
|
|
|
if (!GetCommTimeouts (hnd, &ct))
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
ct.ReadIntervalTimeout = 0;
|
|
|
|
|
ct.ReadTotalTimeoutMultiplier = 0;
|
|
|
|
|
ct.ReadTotalTimeoutConstant = 0;
|
|
|
|
|
if (!SetCommTimeouts (hnd, &ct))
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
|
|
|
|
|
if (!ReadFile (hnd, &cp->chr, sizeof (char), (DWORD*) &rc, ovl))
|
|
|
|
|
{
|
|
|
|
|
if (GetLastError () != ERROR_IO_PENDING)
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS
|
|
|
|
|
else if (fd_info[fd].flags & FILE_SOCKET)
|
2002-05-03 20:40:03 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned long nblock = 0;
|
|
|
|
|
/* We always want this to block, so temporarily disable NDELAY. */
|
|
|
|
|
if (fd_info[fd].flags & FILE_NDELAY)
|
|
|
|
|
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
|
|
|
|
|
|
|
|
|
|
rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
|
|
|
|
|
|
|
|
|
|
if (fd_info[fd].flags & FILE_NDELAY)
|
|
|
|
|
{
|
|
|
|
|
nblock = 1;
|
|
|
|
|
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
|
|
|
|
|
}
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (rc == sizeof (char))
|
|
|
|
|
cp->status = STATUS_READ_SUCCEEDED;
|
|
|
|
|
else
|
|
|
|
|
cp->status = STATUS_READ_FAILED;
|
|
|
|
|
|
|
|
|
|
return cp->status;
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-27 21:55:59 +00:00
|
|
|
|
int
|
|
|
|
|
_sys_wait_accept (int fd)
|
2006-07-14 14:18:40 +00:00
|
|
|
|
{
|
|
|
|
|
HANDLE hEv;
|
|
|
|
|
child_process * cp;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
if (fd < 0 || fd >= MAXDESC)
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
|
|
|
|
|
cp = fd_info[fd].cp;
|
|
|
|
|
|
|
|
|
|
if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
|
|
|
|
|
return STATUS_READ_ERROR;
|
|
|
|
|
|
|
|
|
|
cp->status = STATUS_READ_FAILED;
|
|
|
|
|
|
|
|
|
|
hEv = pfn_WSACreateEvent ();
|
|
|
|
|
rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
|
|
|
|
|
if (rc != SOCKET_ERROR)
|
|
|
|
|
{
|
|
|
|
|
rc = WaitForSingleObject (hEv, INFINITE);
|
|
|
|
|
pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
|
|
|
|
|
if (rc == WAIT_OBJECT_0)
|
|
|
|
|
cp->status = STATUS_READ_SUCCEEDED;
|
|
|
|
|
}
|
2006-12-21 12:47:06 +00:00
|
|
|
|
pfn_WSACloseEvent (hEv);
|
2006-07-14 14:18:40 +00:00
|
|
|
|
|
|
|
|
|
return cp->status;
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
int
|
|
|
|
|
sys_read (int fd, char * buffer, unsigned int count)
|
|
|
|
|
{
|
|
|
|
|
int nchars;
|
|
|
|
|
int to_read;
|
|
|
|
|
DWORD waiting;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
char * orig_buffer = buffer;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (fd < 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
child_process *cp = fd_info[fd].cp;
|
|
|
|
|
|
|
|
|
|
if ((fd_info[fd].flags & FILE_READ) == 0)
|
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
nchars = 0;
|
|
|
|
|
|
|
|
|
|
/* re-read CR carried over from last read */
|
|
|
|
|
if (fd_info[fd].flags & FILE_LAST_CR)
|
|
|
|
|
{
|
|
|
|
|
if (fd_info[fd].flags & FILE_BINARY) abort ();
|
|
|
|
|
*buffer++ = 0x0d;
|
|
|
|
|
count--;
|
|
|
|
|
nchars++;
|
1998-04-17 05:07:15 +00:00
|
|
|
|
fd_info[fd].flags &= ~FILE_LAST_CR;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* presence of a child_process structure means we are operating in
|
|
|
|
|
non-blocking mode - otherwise we just call _read directly.
|
|
|
|
|
Note that the child_process structure might be missing because
|
|
|
|
|
reap_subprocess has been called; in this case the pipe is
|
|
|
|
|
already broken, so calling _read on it is okay. */
|
|
|
|
|
if (cp)
|
|
|
|
|
{
|
|
|
|
|
int current_status = cp->status;
|
|
|
|
|
|
|
|
|
|
switch (current_status)
|
|
|
|
|
{
|
|
|
|
|
case STATUS_READ_FAILED:
|
|
|
|
|
case STATUS_READ_ERROR:
|
1998-04-17 05:07:15 +00:00
|
|
|
|
/* report normal EOF if nothing in buffer */
|
|
|
|
|
if (nchars <= 0)
|
|
|
|
|
fd_info[fd].flags |= FILE_AT_EOF;
|
|
|
|
|
return nchars;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
case STATUS_READ_READY:
|
|
|
|
|
case STATUS_READ_IN_PROGRESS:
|
|
|
|
|
DebPrint (("sys_read called when read is in progress\n"));
|
|
|
|
|
errno = EWOULDBLOCK;
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
case STATUS_READ_SUCCEEDED:
|
|
|
|
|
/* consume read-ahead char */
|
|
|
|
|
*buffer++ = cp->chr;
|
|
|
|
|
count--;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
nchars++;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
cp->status = STATUS_READ_ACKNOWLEDGED;
|
|
|
|
|
ResetEvent (cp->char_avail);
|
|
|
|
|
|
|
|
|
|
case STATUS_READ_ACKNOWLEDGED:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
DebPrint (("sys_read: bad status %d\n", current_status));
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fd_info[fd].flags & FILE_PIPE)
|
|
|
|
|
{
|
|
|
|
|
PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
|
|
|
|
|
to_read = min (waiting, (DWORD) count);
|
1998-04-17 05:07:15 +00:00
|
|
|
|
|
|
|
|
|
if (to_read > 0)
|
|
|
|
|
nchars += _read (fd, buffer, to_read);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
else if (fd_info[fd].flags & FILE_SERIAL)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hnd = fd_info[fd].hnd;
|
|
|
|
|
OVERLAPPED *ovl = &fd_info[fd].cp->ovl_read;
|
|
|
|
|
DWORD err = 0;
|
|
|
|
|
int rc = 0;
|
|
|
|
|
COMMTIMEOUTS ct;
|
|
|
|
|
|
|
|
|
|
if (count > 0)
|
|
|
|
|
{
|
|
|
|
|
/* Configure timeouts for non-blocking read. */
|
|
|
|
|
if (!GetCommTimeouts (hnd, &ct))
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ct.ReadIntervalTimeout = MAXDWORD;
|
|
|
|
|
ct.ReadTotalTimeoutMultiplier = 0;
|
|
|
|
|
ct.ReadTotalTimeoutConstant = 0;
|
|
|
|
|
if (!SetCommTimeouts (hnd, &ct))
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ResetEvent (ovl->hEvent))
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (!ReadFile (hnd, buffer, count, (DWORD*) &rc, ovl))
|
|
|
|
|
{
|
|
|
|
|
if (GetLastError () != ERROR_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (!GetOverlappedResult (hnd, ovl, (DWORD*) &rc, TRUE))
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nchars += rc;
|
|
|
|
|
}
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS
|
|
|
|
|
else /* FILE_SOCKET */
|
|
|
|
|
{
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL) abort ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
/* do the equivalent of a non-blocking read */
|
|
|
|
|
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
if (waiting == 0 && nchars == 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
h_errno = errno = EWOULDBLOCK;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (waiting)
|
|
|
|
|
{
|
|
|
|
|
/* always use binary mode for sockets */
|
1997-09-03 00:43:20 +00:00
|
|
|
|
int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
|
|
|
|
|
if (res == SOCKET_ERROR)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
|
|
|
|
|
pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
|
1997-09-03 00:43:20 +00:00
|
|
|
|
set_errno ();
|
|
|
|
|
return -1;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
nchars += res;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else
|
1998-04-17 05:07:15 +00:00
|
|
|
|
{
|
|
|
|
|
int nread = _read (fd, buffer, count);
|
|
|
|
|
if (nread >= 0)
|
|
|
|
|
nchars += nread;
|
|
|
|
|
else if (nchars == 0)
|
|
|
|
|
nchars = nread;
|
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
1998-04-17 05:07:15 +00:00
|
|
|
|
if (nchars <= 0)
|
|
|
|
|
fd_info[fd].flags |= FILE_AT_EOF;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
/* Perform text mode translation if required. */
|
1998-04-17 05:07:15 +00:00
|
|
|
|
else if ((fd_info[fd].flags & FILE_BINARY) == 0)
|
1997-09-03 00:43:20 +00:00
|
|
|
|
{
|
|
|
|
|
nchars = crlf_to_lf (nchars, orig_buffer);
|
|
|
|
|
/* If buffer contains only CR, return that. To be absolutely
|
|
|
|
|
sure we should attempt to read the next char, but in
|
|
|
|
|
practice a CR to be followed by LF would not appear by
|
|
|
|
|
itself in the buffer. */
|
|
|
|
|
if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
|
|
|
|
|
{
|
|
|
|
|
fd_info[fd].flags |= FILE_LAST_CR;
|
|
|
|
|
nchars--;
|
|
|
|
|
}
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
nchars = _read (fd, buffer, count);
|
|
|
|
|
|
1997-09-03 00:43:20 +00:00
|
|
|
|
return nchars;
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
/* From w32xfns.c */
|
|
|
|
|
extern HANDLE interrupt_handle;
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
/* For now, don't bother with a non-blocking mode */
|
|
|
|
|
int
|
|
|
|
|
sys_write (int fd, const void * buffer, unsigned int count)
|
|
|
|
|
{
|
|
|
|
|
int nchars;
|
|
|
|
|
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (fd < 0)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET | FILE_SERIAL))
|
1997-09-03 00:43:20 +00:00
|
|
|
|
{
|
|
|
|
|
if ((fd_info[fd].flags & FILE_WRITE) == 0)
|
|
|
|
|
{
|
|
|
|
|
errno = EBADF;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Perform text mode translation if required. */
|
|
|
|
|
if ((fd_info[fd].flags & FILE_BINARY) == 0)
|
|
|
|
|
{
|
|
|
|
|
char * tmpbuf = alloca (count * 2);
|
|
|
|
|
unsigned char * src = (void *)buffer;
|
|
|
|
|
unsigned char * dst = tmpbuf;
|
|
|
|
|
int nbytes = count;
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
unsigned char *next;
|
|
|
|
|
/* copy next line or remaining bytes */
|
|
|
|
|
next = _memccpy (dst, src, '\n', nbytes);
|
|
|
|
|
if (next)
|
|
|
|
|
{
|
|
|
|
|
/* copied one line ending with '\n' */
|
|
|
|
|
int copied = next - dst;
|
|
|
|
|
nbytes -= copied;
|
|
|
|
|
src += copied;
|
|
|
|
|
/* insert '\r' before '\n' */
|
|
|
|
|
next[-1] = '\r';
|
|
|
|
|
next[0] = '\n';
|
|
|
|
|
dst = next + 1;
|
|
|
|
|
count++;
|
2003-02-04 14:56:31 +00:00
|
|
|
|
}
|
1997-09-03 00:43:20 +00:00
|
|
|
|
else
|
|
|
|
|
/* copied remaining partial line -> now finished */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
buffer = tmpbuf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
if (fd < MAXDESC && fd_info[fd].flags & FILE_SERIAL)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hnd = (HANDLE) _get_osfhandle (fd);
|
|
|
|
|
OVERLAPPED *ovl = &fd_info[fd].cp->ovl_write;
|
|
|
|
|
HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent };
|
|
|
|
|
DWORD active = 0;
|
|
|
|
|
|
|
|
|
|
if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl))
|
|
|
|
|
{
|
|
|
|
|
if (GetLastError () != ERROR_IO_PENDING)
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (detect_input_pending ())
|
|
|
|
|
active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE,
|
|
|
|
|
QS_ALLINPUT);
|
|
|
|
|
else
|
|
|
|
|
active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE);
|
|
|
|
|
if (active == WAIT_OBJECT_0)
|
|
|
|
|
{ /* User pressed C-g, cancel write, then leave. Don't bother
|
|
|
|
|
cleaning up as we may only get stuck in buggy drivers. */
|
|
|
|
|
PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR);
|
|
|
|
|
CancelIo (hnd);
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (active == WAIT_OBJECT_0 + 1
|
|
|
|
|
&& !GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE))
|
|
|
|
|
{
|
|
|
|
|
errno = EIO;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#ifdef HAVE_SOCKETS
|
2006-01-20 19:12:39 +00:00
|
|
|
|
if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
|
1996-05-03 18:32:52 +00:00
|
|
|
|
{
|
2002-11-25 23:30:19 +00:00
|
|
|
|
unsigned long nblock = 0;
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
if (winsock_lib == NULL) abort ();
|
2002-11-25 23:30:19 +00:00
|
|
|
|
|
|
|
|
|
/* TODO: implement select() properly so non-blocking I/O works. */
|
|
|
|
|
/* For now, make sure the write blocks. */
|
|
|
|
|
if (fd_info[fd].flags & FILE_NDELAY)
|
|
|
|
|
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
|
2002-11-25 23:30:19 +00:00
|
|
|
|
|
|
|
|
|
/* Set the socket back to non-blocking if it was before,
|
|
|
|
|
for other operations that support it. */
|
|
|
|
|
if (fd_info[fd].flags & FILE_NDELAY)
|
|
|
|
|
{
|
|
|
|
|
nblock = 1;
|
|
|
|
|
pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
|
|
|
|
|
}
|
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
if (nchars == SOCKET_ERROR)
|
|
|
|
|
{
|
2002-11-27 23:48:33 +00:00
|
|
|
|
DebPrint(("sys_write.send failed with error %d on socket %ld\n",
|
1996-05-03 18:32:52 +00:00
|
|
|
|
pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
|
|
|
|
|
set_errno ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
nchars = _write (fd, buffer, count);
|
|
|
|
|
|
|
|
|
|
return nchars;
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-17 05:07:15 +00:00
|
|
|
|
static void
|
|
|
|
|
check_windows_init_file ()
|
|
|
|
|
{
|
|
|
|
|
extern int noninteractive, inhibit_window_system;
|
|
|
|
|
|
|
|
|
|
/* A common indication that Emacs is not installed properly is when
|
|
|
|
|
it cannot find the Windows installation file. If this file does
|
|
|
|
|
not exist in the expected place, tell the user. */
|
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
if (!noninteractive && !inhibit_window_system)
|
1998-10-07 19:47:48 +00:00
|
|
|
|
{
|
|
|
|
|
extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
|
1998-12-03 03:14:46 +00:00
|
|
|
|
Lisp_Object objs[2];
|
1998-10-27 23:42:26 +00:00
|
|
|
|
Lisp_Object full_load_path;
|
1998-10-07 19:47:48 +00:00
|
|
|
|
Lisp_Object init_file;
|
|
|
|
|
int fd;
|
1998-04-17 05:07:15 +00:00
|
|
|
|
|
1998-12-03 03:14:46 +00:00
|
|
|
|
objs[0] = Vload_path;
|
|
|
|
|
objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
|
|
|
|
|
full_load_path = Fappend (2, objs);
|
1998-10-07 19:47:48 +00:00
|
|
|
|
init_file = build_string ("term/w32-win");
|
2006-02-27 02:07:37 +00:00
|
|
|
|
fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
if (fd < 0)
|
1998-10-07 19:47:48 +00:00
|
|
|
|
{
|
1998-10-27 23:42:26 +00:00
|
|
|
|
Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
|
2002-07-15 00:01:34 +00:00
|
|
|
|
char *init_file_name = SDATA (init_file);
|
|
|
|
|
char *load_path = SDATA (load_path_print);
|
2005-09-12 10:27:02 +00:00
|
|
|
|
char *buffer = alloca (1024
|
|
|
|
|
+ strlen (init_file_name)
|
|
|
|
|
+ strlen (load_path));
|
1998-10-07 19:47:48 +00:00
|
|
|
|
|
2003-02-04 14:56:31 +00:00
|
|
|
|
sprintf (buffer,
|
1998-10-07 19:47:48 +00:00
|
|
|
|
"The Emacs Windows initialization file \"%s.el\" "
|
|
|
|
|
"could not be found in your Emacs installation. "
|
|
|
|
|
"Emacs checked the following directories for this file:\n"
|
|
|
|
|
"\n%s\n\n"
|
|
|
|
|
"When Emacs cannot find this file, it usually means that it "
|
|
|
|
|
"was not installed properly, or its distribution file was "
|
|
|
|
|
"not unpacked properly.\nSee the README.W32 file in the "
|
|
|
|
|
"top-level Emacs directory for more information.",
|
|
|
|
|
init_file_name, load_path);
|
|
|
|
|
MessageBox (NULL,
|
|
|
|
|
buffer,
|
|
|
|
|
"Emacs Abort Dialog",
|
|
|
|
|
MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
|
1998-04-17 05:07:15 +00:00
|
|
|
|
/* Use the low-level Emacs abort. */
|
|
|
|
|
#undef abort
|
1998-10-07 19:47:48 +00:00
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2000-08-22 22:49:27 +00:00
|
|
|
|
_close (fd);
|
1998-10-07 19:47:48 +00:00
|
|
|
|
}
|
1998-04-17 05:07:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
term_ntproc ()
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SOCKETS
|
|
|
|
|
/* shutdown the socket interface if necessary */
|
|
|
|
|
term_winsock ();
|
|
|
|
|
#endif
|
2004-11-08 Benjamin Riefenstahl <Benjamin.Riefenstahl@epost.de>
* w32select.c: Summary: Thorough rework to implement Unicode
clipboard operations and delayed rendering.
Drop last_clipboard_text and related code, keep track of
ownership via clipboard_owner instead. Drop old #if0
sections.
(DEFAULT_LCID, ANSICP, OEMCP, QUNICODE, QANSICP, QOEMCP)
(clipboard_owner, modifying_clipboard, cfg_coding_system)
(cfg_codepage, cfg_lcid, cfg_clipboard_type, current_text)
(current_coding_system, current_requires_encoding)
(current_num_nls, current_clipboard_type, current_lcid): New
static variables.
(convert_to_handle_as_ascii, convert_to_handle_as_coded)
(render, render_all, run_protected, lisp_error_handler)
(owner_callback, create_owner, setup_config)
(enum_locale_callback, cp_from_locale, coding_from_cp): New
local functions.
(term_w32select, globals_of_w32select): New global functions.
(Fw32_set_clipboard_data): Ignore parameter FRAME, use
clipboard_owner instead. Use delayed rendering and provide
all text formats. Provide CF_LOCALE if necessary.
(Fw32_get_clipboard_data): Handle CF_UNICODETEXT and
CF_LOCALE. Fall back to CF_TEXT, if CF_UNICODETEXT is not
available. Force DOS line-ends for decoding.
(Fx_selection_exists_p): Handle CF_UNICODETEXT.
(syms_of_w32select): Init and register new variables.
* w32.h: Add prototypes for globals_of_w32select and
term_w32select. Make the neighboring K&R declarations into
prototypes, too.
* emacs.c: Include w32.h to get function prototypes.
(main): Call globals_of_w32select.
* w32.c (term_ntproc): Call term_w32select.
* mule-cmds.el (set-locale-environment): Remove call to
set-selection-coding-system on Windows.
* s/ms-w32.h: Guard MSC-specific #pragmas with an #ifdef.
2005-02-15 23:19:26 +00:00
|
|
|
|
|
|
|
|
|
term_w32select ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
init_ntproc ()
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SOCKETS
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
/* Initialise the socket interface now if available and requested by
|
|
|
|
|
the user by defining PRELOAD_WINSOCK; otherwise loading will be
|
1996-11-19 04:59:23 +00:00
|
|
|
|
delayed until open-network-stream is called (w32-has-winsock can
|
(init_environment): Read PRELOAD_WINSOCK from registry if
not set in environment.
(winsock_inuse) [HAVE_SOCKETS]: New variable.
(have_winsock) [HAVE_SOCKETS]: Obsolete variable removed.
(term_winsock) [HAVE_SOCKETS]: Only unload winsock library if there
are no active sockets still open, and if the cleanup function
succeeds. Return TRUE if winsock is unloaded.
(init_winsock) [HAVE_SOCKETS]: Load winsock if not already loaded,
and return TRUE if winsock support is available. Unload winsock
immediately if new parameter load_now is false. Check that
WSAStartup supports the winsock version we requested.
(set_errno, check_errno, sys_socket, sys_bind, sys_connect, sys_htons,
sys_ntohs, sys_inet_addr, sys_gethostname, sys_gethostbyname,
sys_getservbyname, sys_close, sys_read, sys_write) [HAVE_SOCKETS]:
Check winsock_lib instead of have_winsock to determine if winsock
support is available.
(sys_socket, sys_close) [HAVE_SOCKETS]: Count sockets in use.
(init_ntproc) [HAVE_SOCKETS]: Only load winsock library on startup
if PRELOAD_WINSOCK is set in environment (or registry).
1996-06-08 00:22:50 +00:00
|
|
|
|
also be used to dynamically load or reload winsock).
|
|
|
|
|
|
|
|
|
|
Conveniently, init_environment is called before us, so
|
|
|
|
|
PRELOAD_WINSOCK can be set in the registry. */
|
|
|
|
|
|
|
|
|
|
/* Always initialize this correctly. */
|
|
|
|
|
winsock_lib = NULL;
|
|
|
|
|
|
|
|
|
|
if (getenv ("PRELOAD_WINSOCK") != NULL)
|
|
|
|
|
init_winsock (TRUE);
|
1996-05-03 18:32:52 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Initial preparation for subprocess support: replace our standard
|
|
|
|
|
handles with non-inheritable versions. */
|
|
|
|
|
{
|
|
|
|
|
HANDLE parent;
|
|
|
|
|
HANDLE stdin_save = INVALID_HANDLE_VALUE;
|
|
|
|
|
HANDLE stdout_save = INVALID_HANDLE_VALUE;
|
|
|
|
|
HANDLE stderr_save = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
|
|
parent = GetCurrentProcess ();
|
|
|
|
|
|
|
|
|
|
/* ignore errors when duplicating and closing; typically the
|
|
|
|
|
handles will be invalid when running as a gui program. */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
DuplicateHandle (parent,
|
|
|
|
|
GetStdHandle (STD_INPUT_HANDLE),
|
1996-05-03 18:32:52 +00:00
|
|
|
|
parent,
|
2003-02-04 14:56:31 +00:00
|
|
|
|
&stdin_save,
|
|
|
|
|
0,
|
|
|
|
|
FALSE,
|
1996-05-03 18:32:52 +00:00
|
|
|
|
DUPLICATE_SAME_ACCESS);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
DuplicateHandle (parent,
|
|
|
|
|
GetStdHandle (STD_OUTPUT_HANDLE),
|
|
|
|
|
parent,
|
|
|
|
|
&stdout_save,
|
|
|
|
|
0,
|
|
|
|
|
FALSE,
|
|
|
|
|
DUPLICATE_SAME_ACCESS);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
DuplicateHandle (parent,
|
|
|
|
|
GetStdHandle (STD_ERROR_HANDLE),
|
|
|
|
|
parent,
|
|
|
|
|
&stderr_save,
|
|
|
|
|
0,
|
|
|
|
|
FALSE,
|
|
|
|
|
DUPLICATE_SAME_ACCESS);
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1996-05-03 18:32:52 +00:00
|
|
|
|
fclose (stdin);
|
|
|
|
|
fclose (stdout);
|
|
|
|
|
fclose (stderr);
|
|
|
|
|
|
|
|
|
|
if (stdin_save != INVALID_HANDLE_VALUE)
|
|
|
|
|
_open_osfhandle ((long) stdin_save, O_TEXT);
|
|
|
|
|
else
|
1997-09-03 00:43:20 +00:00
|
|
|
|
_open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
|
|
|
|
|
_fdopen (0, "r");
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (stdout_save != INVALID_HANDLE_VALUE)
|
|
|
|
|
_open_osfhandle ((long) stdout_save, O_TEXT);
|
|
|
|
|
else
|
1997-09-03 00:43:20 +00:00
|
|
|
|
_open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
|
|
|
|
|
_fdopen (1, "w");
|
1996-05-03 18:32:52 +00:00
|
|
|
|
|
|
|
|
|
if (stderr_save != INVALID_HANDLE_VALUE)
|
|
|
|
|
_open_osfhandle ((long) stderr_save, O_TEXT);
|
|
|
|
|
else
|
1997-09-03 00:43:20 +00:00
|
|
|
|
_open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
|
|
|
|
|
_fdopen (2, "w");
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* unfortunately, atexit depends on implementation of malloc */
|
|
|
|
|
/* atexit (term_ntproc); */
|
|
|
|
|
signal (SIGABRT, term_ntproc);
|
1997-09-03 00:43:20 +00:00
|
|
|
|
|
|
|
|
|
/* determine which drives are fixed, for GetCachedVolumeInformation */
|
|
|
|
|
{
|
|
|
|
|
/* GetDriveType must have trailing backslash. */
|
|
|
|
|
char drive[] = "A:\\";
|
|
|
|
|
|
|
|
|
|
/* Loop over all possible drive letters */
|
|
|
|
|
while (*drive <= 'Z')
|
|
|
|
|
{
|
|
|
|
|
/* Record if this drive letter refers to a fixed drive. */
|
2003-02-04 14:56:31 +00:00
|
|
|
|
fixed_drives[DRIVE_INDEX (*drive)] =
|
1997-09-03 00:43:20 +00:00
|
|
|
|
(GetDriveType (drive) == DRIVE_FIXED);
|
|
|
|
|
|
|
|
|
|
(*drive)++;
|
|
|
|
|
}
|
2000-08-22 22:49:27 +00:00
|
|
|
|
|
|
|
|
|
/* Reset the volume info cache. */
|
|
|
|
|
volume_cache = NULL;
|
1997-09-03 00:43:20 +00:00
|
|
|
|
}
|
2003-02-04 14:56:31 +00:00
|
|
|
|
|
1998-10-07 19:47:48 +00:00
|
|
|
|
/* Check to see if Emacs has been installed correctly. */
|
|
|
|
|
check_windows_init_file ();
|
1996-05-03 18:32:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-09-03 22:51:22 +00:00
|
|
|
|
/*
|
|
|
|
|
shutdown_handler ensures that buffers' autosave files are
|
|
|
|
|
up to date when the user logs off, or the system shuts down.
|
|
|
|
|
*/
|
|
|
|
|
BOOL WINAPI shutdown_handler(DWORD type)
|
|
|
|
|
{
|
|
|
|
|
/* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
|
|
|
|
|
if (type == CTRL_CLOSE_EVENT /* User closes console window. */
|
|
|
|
|
|| type == CTRL_LOGOFF_EVENT /* User logs off. */
|
|
|
|
|
|| type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
|
|
|
|
|
{
|
|
|
|
|
/* Shut down cleanly, making sure autosave files are up to date. */
|
|
|
|
|
shut_down_emacs (0, 0, Qnil);
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-21 12:47:06 +00:00
|
|
|
|
/* Allow other handlers to handle this signal. */
|
2006-09-03 22:51:22 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2002-12-18 06:16:28 +00:00
|
|
|
|
/*
|
|
|
|
|
globals_of_w32 is used to initialize those global variables that
|
|
|
|
|
must always be initialized on startup even when the global variable
|
|
|
|
|
initialized is non zero (see the function main in emacs.c).
|
|
|
|
|
*/
|
2006-12-27 21:55:59 +00:00
|
|
|
|
void
|
|
|
|
|
globals_of_w32 ()
|
2002-12-18 06:16:28 +00:00
|
|
|
|
{
|
2007-06-14 15:58:13 +00:00
|
|
|
|
HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
|
|
|
|
|
|
|
|
|
|
get_process_times_fn = (GetProcessTimes_Proc)
|
|
|
|
|
GetProcAddress (kernel32, "GetProcessTimes");
|
|
|
|
|
|
2002-12-18 06:16:28 +00:00
|
|
|
|
g_b_init_is_windows_9x = 0;
|
|
|
|
|
g_b_init_open_process_token = 0;
|
|
|
|
|
g_b_init_get_token_information = 0;
|
|
|
|
|
g_b_init_lookup_account_sid = 0;
|
|
|
|
|
g_b_init_get_sid_identifier_authority = 0;
|
2008-02-23 13:38:12 +00:00
|
|
|
|
g_b_init_get_sid_sub_authority = 0;
|
|
|
|
|
g_b_init_get_sid_sub_authority_count = 0;
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
g_b_init_get_file_security = 0;
|
|
|
|
|
g_b_init_get_security_descriptor_owner = 0;
|
|
|
|
|
g_b_init_get_security_descriptor_group = 0;
|
|
|
|
|
g_b_init_is_valid_sid = 0;
|
Include thelp32.h, psapi.h and coding.h.
(_MEMORYSTATUSEX, _PROCESS_MEMORY_COUNTERS_EX): New struct declarations.
(CreateToolhelp32Snapshot_Proc, Process32First_Proc, Process32Next_Proc): New
typedefs.
(g_b_init_create_toolhelp32_snapshot, g_b_init_process32_first)
(g_b_init_process32_next, g_b_init_open_thread_token)
(g_b_init_impersonate_self, g_b_init_revert_to_self)
(g_b_init_get_process_memory_info, g_b_init_global_memory_status)
(g_b_init_get_process_working_set_size)
(g_b_init_global_memory_status_ex): New static variables.
(globals_of_w32): Initialize them.
(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): New wrapper functions.
(w32_list_system_processes, w32_system_process_attributes)
(enable_privilege, restore_privilege, ltime, process_times): New functions.
(convert_time_raw): New function.
(convert_time): Remove conversion of FILETIME into time in 100 nsec units,
call convert_time_raw instead.
2008-08-09 17:53:00 +00:00
|
|
|
|
g_b_init_create_toolhelp32_snapshot = 0;
|
|
|
|
|
g_b_init_process32_first = 0;
|
|
|
|
|
g_b_init_process32_next = 0;
|
|
|
|
|
g_b_init_open_thread_token = 0;
|
|
|
|
|
g_b_init_impersonate_self = 0;
|
|
|
|
|
g_b_init_revert_to_self = 0;
|
|
|
|
|
g_b_init_get_process_memory_info = 0;
|
|
|
|
|
g_b_init_get_process_working_set_size = 0;
|
|
|
|
|
g_b_init_global_memory_status = 0;
|
|
|
|
|
g_b_init_global_memory_status_ex = 0;
|
2008-08-15 16:00:19 +00:00
|
|
|
|
g_b_init_equal_sid = 0;
|
|
|
|
|
g_b_init_copy_sid = 0;
|
|
|
|
|
g_b_init_get_length_sid = 0;
|
2009-07-04 10:43:10 +00:00
|
|
|
|
g_b_init_get_native_system_info = 0;
|
|
|
|
|
g_b_init_get_system_times = 0;
|
|
|
|
|
num_of_processors = 0;
|
2006-09-03 22:51:22 +00:00
|
|
|
|
/* The following sets a handler for shutdown notifications for
|
|
|
|
|
console apps. This actually applies to Emacs in both console and
|
|
|
|
|
GUI modes, since we had to fool windows into thinking emacs is a
|
|
|
|
|
console application to get console mode to work. */
|
|
|
|
|
SetConsoleCtrlHandler(shutdown_handler, TRUE);
|
Support for reporting owner and group of each file on MS-Windows:
* dired.c (stat_uname, stat_gname): New functions, with special
implementation for w32.
(Ffile_attributes): Use them instead of getpwuid and getgrgid.
* w32.c:
(g_b_init_get_file_security, g_b_init_get_security_descriptor_owner)
(g_b_init_get_security_descriptor_group, g_b_init_is_valid_sid):
New initialization states.
(globals_of_w32): Initialize them to zero. Initialize the default
group name to "None".
(GetFileSecurity_Name): New global var, the name of the function
to call for GetFileSecurity.
(GetFileSecurity_Proc, GetSecurityDescriptorOwner_Proc)
(GetSecurityDescriptorGroup_Proc, IsValidSid_Proc): New typedefs.
(get_file_security, get_security_descriptor_owner)
(get_security_descriptor_group, is_valid_sid)
(get_file_security_desc, get_rid, get_name_and_id)
(get_file_owner_and_group): New functions.
(stat): Use get_file_security_desc and get_file_owner_and_group to
report the owner and primary group of each file. Don't ignore the
high 32 bits of file's size, now that st_size is 64-bit wide. Fix
test when to get true file attributes.
(init_user_info): Use get_rid instead of equivalent inline code.
(fstat): Don't ignore the high 32 bits of file's size.
2008-05-09 19:03:52 +00:00
|
|
|
|
|
|
|
|
|
/* "None" is the default group name on standalone workstations. */
|
|
|
|
|
strcpy (dflt_group_name, "None");
|
2002-12-18 06:16:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
Daniel Engeler <engeler at gmail.com>
These changes add serial port access.
* process.c: Add HAVE_SERIAL.
(Fdelete_process, Fprocess_status, Fset_process_buffer)
(Fset_process_filter, Fset_process_sentinel, Fprocess_contact)
(list_processes_1, select_wrapper, Fstop_process)
(Fcontinue_process, Fprocess_send_eof, kill_buffer_processes)
(status_notify): Modify to handle serial processes.
[HAVE_SERIAL] (Fserial_process_configure)
[HAVE_SERIAL] (make_serial_process_unwind, Fmake_serial_process):
New functions.
* process.h (struct Lisp_Process): Add `type'.
* sysdep.c [HAVE_TERMIOS] (serial_open, serial_configure):
New functions.
* w32.c (_sys_read_ahead, sys_read, sys_write): Modify to handle serial ports.
(serial_open, serial_configure) New functions.
* w32.h: Add FILE_SERIAL.
(struct _child_process): Add ovl_read, ovl_write.
2008-06-13 08:08:20 +00:00
|
|
|
|
/* For make-serial-process */
|
|
|
|
|
int serial_open (char *port)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hnd;
|
|
|
|
|
child_process *cp;
|
|
|
|
|
int fd = -1;
|
|
|
|
|
|
|
|
|
|
hnd = CreateFile (port, GENERIC_READ | GENERIC_WRITE, 0, 0,
|
|
|
|
|
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
|
|
|
|
if (hnd == INVALID_HANDLE_VALUE)
|
|
|
|
|
error ("Could not open %s", port);
|
|
|
|
|
fd = (int) _open_osfhandle ((int) hnd, 0);
|
|
|
|
|
if (fd == -1)
|
|
|
|
|
error ("Could not open %s", port);
|
|
|
|
|
|
|
|
|
|
cp = new_child ();
|
|
|
|
|
if (!cp)
|
|
|
|
|
error ("Could not create child process");
|
|
|
|
|
cp->fd = fd;
|
|
|
|
|
cp->status = STATUS_READ_ACKNOWLEDGED;
|
|
|
|
|
fd_info[ fd ].hnd = hnd;
|
|
|
|
|
fd_info[ fd ].flags |=
|
|
|
|
|
FILE_READ | FILE_WRITE | FILE_BINARY | FILE_SERIAL;
|
|
|
|
|
if (fd_info[ fd ].cp != NULL)
|
|
|
|
|
{
|
|
|
|
|
error ("fd_info[fd = %d] is already in use", fd);
|
|
|
|
|
}
|
|
|
|
|
fd_info[ fd ].cp = cp;
|
|
|
|
|
cp->ovl_read.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
|
|
|
|
|
if (cp->ovl_read.hEvent == NULL)
|
|
|
|
|
error ("Could not create read event");
|
|
|
|
|
cp->ovl_write.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
|
|
|
|
|
if (cp->ovl_write.hEvent == NULL)
|
|
|
|
|
error ("Could not create write event");
|
|
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For serial-process-configure */
|
|
|
|
|
void
|
|
|
|
|
serial_configure (struct Lisp_Process *p,
|
|
|
|
|
Lisp_Object contact)
|
|
|
|
|
{
|
|
|
|
|
Lisp_Object childp2 = Qnil;
|
|
|
|
|
Lisp_Object tem = Qnil;
|
|
|
|
|
HANDLE hnd;
|
|
|
|
|
DCB dcb;
|
|
|
|
|
COMMTIMEOUTS ct;
|
|
|
|
|
char summary[4] = "???"; /* This usually becomes "8N1". */
|
|
|
|
|
|
|
|
|
|
if ((fd_info[ p->outfd ].flags & FILE_SERIAL) == 0)
|
|
|
|
|
error ("Not a serial process");
|
|
|
|
|
hnd = fd_info[ p->outfd ].hnd;
|
|
|
|
|
|
|
|
|
|
childp2 = Fcopy_sequence (p->childp);
|
|
|
|
|
|
|
|
|
|
/* Initialize timeouts for blocking read and blocking write. */
|
|
|
|
|
if (!GetCommTimeouts (hnd, &ct))
|
|
|
|
|
error ("GetCommTimeouts() failed");
|
|
|
|
|
ct.ReadIntervalTimeout = 0;
|
|
|
|
|
ct.ReadTotalTimeoutMultiplier = 0;
|
|
|
|
|
ct.ReadTotalTimeoutConstant = 0;
|
|
|
|
|
ct.WriteTotalTimeoutMultiplier = 0;
|
|
|
|
|
ct.WriteTotalTimeoutConstant = 0;
|
|
|
|
|
if (!SetCommTimeouts (hnd, &ct))
|
|
|
|
|
error ("SetCommTimeouts() failed");
|
|
|
|
|
/* Read port attributes and prepare default configuration. */
|
|
|
|
|
memset (&dcb, 0, sizeof (dcb));
|
|
|
|
|
dcb.DCBlength = sizeof (DCB);
|
|
|
|
|
if (!GetCommState (hnd, &dcb))
|
|
|
|
|
error ("GetCommState() failed");
|
|
|
|
|
dcb.fBinary = TRUE;
|
|
|
|
|
dcb.fNull = FALSE;
|
|
|
|
|
dcb.fAbortOnError = FALSE;
|
|
|
|
|
/* dcb.XonLim and dcb.XoffLim are set by GetCommState() */
|
|
|
|
|
dcb.ErrorChar = 0;
|
|
|
|
|
dcb.EofChar = 0;
|
|
|
|
|
dcb.EvtChar = 0;
|
|
|
|
|
|
|
|
|
|
/* Configure speed. */
|
|
|
|
|
if (!NILP (Fplist_member (contact, QCspeed)))
|
|
|
|
|
tem = Fplist_get (contact, QCspeed);
|
|
|
|
|
else
|
|
|
|
|
tem = Fplist_get (p->childp, QCspeed);
|
|
|
|
|
CHECK_NUMBER (tem);
|
|
|
|
|
dcb.BaudRate = XINT (tem);
|
|
|
|
|
childp2 = Fplist_put (childp2, QCspeed, tem);
|
|
|
|
|
|
|
|
|
|
/* Configure bytesize. */
|
|
|
|
|
if (!NILP (Fplist_member (contact, QCbytesize)))
|
|
|
|
|
tem = Fplist_get (contact, QCbytesize);
|
|
|
|
|
else
|
|
|
|
|
tem = Fplist_get (p->childp, QCbytesize);
|
|
|
|
|
if (NILP (tem))
|
|
|
|
|
tem = make_number (8);
|
|
|
|
|
CHECK_NUMBER (tem);
|
|
|
|
|
if (XINT (tem) != 7 && XINT (tem) != 8)
|
|
|
|
|
error (":bytesize must be nil (8), 7, or 8");
|
|
|
|
|
dcb.ByteSize = XINT (tem);
|
|
|
|
|
summary[0] = XINT (tem) + '0';
|
|
|
|
|
childp2 = Fplist_put (childp2, QCbytesize, tem);
|
|
|
|
|
|
|
|
|
|
/* Configure parity. */
|
|
|
|
|
if (!NILP (Fplist_member (contact, QCparity)))
|
|
|
|
|
tem = Fplist_get (contact, QCparity);
|
|
|
|
|
else
|
|
|
|
|
tem = Fplist_get (p->childp, QCparity);
|
|
|
|
|
if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd))
|
|
|
|
|
error (":parity must be nil (no parity), `even', or `odd'");
|
|
|
|
|
dcb.fParity = FALSE;
|
|
|
|
|
dcb.Parity = NOPARITY;
|
|
|
|
|
dcb.fErrorChar = FALSE;
|
|
|
|
|
if (NILP (tem))
|
|
|
|
|
{
|
|
|
|
|
summary[1] = 'N';
|
|
|
|
|
}
|
|
|
|
|
else if (EQ (tem, Qeven))
|
|
|
|
|
{
|
|
|
|
|
summary[1] = 'E';
|
|
|
|
|
dcb.fParity = TRUE;
|
|
|
|
|
dcb.Parity = EVENPARITY;
|
|
|
|
|
dcb.fErrorChar = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (EQ (tem, Qodd))
|
|
|
|
|
{
|
|
|
|
|
summary[1] = 'O';
|
|
|
|
|
dcb.fParity = TRUE;
|
|
|
|
|
dcb.Parity = ODDPARITY;
|
|
|
|
|
dcb.fErrorChar = TRUE;
|
|
|
|
|
}
|
|
|
|
|
childp2 = Fplist_put (childp2, QCparity, tem);
|
|
|
|
|
|
|
|
|
|
/* Configure stopbits. */
|
|
|
|
|
if (!NILP (Fplist_member (contact, QCstopbits)))
|
|
|
|
|
tem = Fplist_get (contact, QCstopbits);
|
|
|
|
|
else
|
|
|
|
|
tem = Fplist_get (p->childp, QCstopbits);
|
|
|
|
|
if (NILP (tem))
|
|
|
|
|
tem = make_number (1);
|
|
|
|
|
CHECK_NUMBER (tem);
|
|
|
|
|
if (XINT (tem) != 1 && XINT (tem) != 2)
|
|
|
|
|
error (":stopbits must be nil (1 stopbit), 1, or 2");
|
|
|
|
|
summary[2] = XINT (tem) + '0';
|
|
|
|
|
if (XINT (tem) == 1)
|
|
|
|
|
dcb.StopBits = ONESTOPBIT;
|
|
|
|
|
else if (XINT (tem) == 2)
|
|
|
|
|
dcb.StopBits = TWOSTOPBITS;
|
|
|
|
|
childp2 = Fplist_put (childp2, QCstopbits, tem);
|
|
|
|
|
|
|
|
|
|
/* Configure flowcontrol. */
|
|
|
|
|
if (!NILP (Fplist_member (contact, QCflowcontrol)))
|
|
|
|
|
tem = Fplist_get (contact, QCflowcontrol);
|
|
|
|
|
else
|
|
|
|
|
tem = Fplist_get (p->childp, QCflowcontrol);
|
|
|
|
|
if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw))
|
|
|
|
|
error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'");
|
|
|
|
|
dcb.fOutxCtsFlow = FALSE;
|
|
|
|
|
dcb.fOutxDsrFlow = FALSE;
|
|
|
|
|
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
|
|
|
|
dcb.fDsrSensitivity = FALSE;
|
|
|
|
|
dcb.fTXContinueOnXoff = FALSE;
|
|
|
|
|
dcb.fOutX = FALSE;
|
|
|
|
|
dcb.fInX = FALSE;
|
|
|
|
|
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
|
|
|
|
dcb.XonChar = 17; /* Control-Q */
|
|
|
|
|
dcb.XoffChar = 19; /* Control-S */
|
|
|
|
|
if (NILP (tem))
|
|
|
|
|
{
|
|
|
|
|
/* Already configured. */
|
|
|
|
|
}
|
|
|
|
|
else if (EQ (tem, Qhw))
|
|
|
|
|
{
|
|
|
|
|
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
|
|
|
|
|
dcb.fOutxCtsFlow = TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (EQ (tem, Qsw))
|
|
|
|
|
{
|
|
|
|
|
dcb.fOutX = TRUE;
|
|
|
|
|
dcb.fInX = TRUE;
|
|
|
|
|
}
|
|
|
|
|
childp2 = Fplist_put (childp2, QCflowcontrol, tem);
|
|
|
|
|
|
|
|
|
|
/* Activate configuration. */
|
|
|
|
|
if (!SetCommState (hnd, &dcb))
|
|
|
|
|
error ("SetCommState() failed");
|
|
|
|
|
|
|
|
|
|
childp2 = Fplist_put (childp2, QCsummary, build_string (summary));
|
|
|
|
|
p->childp = childp2;
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-20 08:31:09 +00:00
|
|
|
|
/* end of w32.c */
|
2003-09-01 15:45:59 +00:00
|
|
|
|
|
|
|
|
|
/* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
|
|
|
|
|
(do not change this comment) */
|