aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2008-08-09 17:53:00 +0000
committerEli Zaretskii2008-08-09 17:53:00 +0000
commit7c80d5ec06b0934d72fc278405d0a3a1895bbe6e (patch)
tree8924e56bdb55f3f50345019457a333c861b6f33a /src
parenta96a1d43db8cf18fc4d10992f1f96ad94e5aba13 (diff)
downloademacs-7c80d5ec06b0934d72fc278405d0a3a1895bbe6e.tar.gz
emacs-7c80d5ec06b0934d72fc278405d0a3a1895bbe6e.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c714
1 files changed, 710 insertions, 4 deletions
diff --git a/src/w32.c b/src/w32.c
index c10990bae3b..6bbeb8e092f 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32#include <sys/time.h> 32#include <sys/time.h>
33#include <sys/utime.h> 33#include <sys/utime.h>
34#include <mbstring.h> /* for _mbspbrk */ 34#include <mbstring.h> /* for _mbspbrk */
35#include <math.h>
35 36
36/* must include CRT headers *before* config.h */ 37/* must include CRT headers *before* config.h */
37 38
@@ -72,9 +73,40 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
72#define _ANONYMOUS_STRUCT 73#define _ANONYMOUS_STRUCT
73#endif 74#endif
74#include <windows.h> 75#include <windows.h>
76/* This is guarded by a higher value of _WIN32_WINNT than what we use. */
77typedef struct _MEMORYSTATUSEX {
78 DWORD dwLength;
79 DWORD dwMemoryLoad;
80 DWORDLONG ullTotalPhys;
81 DWORDLONG ullAvailPhys;
82 DWORDLONG ullTotalPageFile;
83 DWORDLONG ullAvailPageFile;
84 DWORDLONG ullTotalVirtual;
85 DWORDLONG ullAvailVirtual;
86 DWORDLONG ullAvailExtendedVirtual;
87} MEMORYSTATUSEX,*LPMEMORYSTATUSEX;
88
75#include <lmcons.h> 89#include <lmcons.h>
76#include <shlobj.h> 90#include <shlobj.h>
77 91
92#include <tlhelp32.h>
93#include <psapi.h>
94/* This either is not in psapi.h or guarded by higher value of
95 _WIN32_WINNT than what we use. */
96typedef struct _PROCESS_MEMORY_COUNTERS_EX {
97 DWORD cb;
98 DWORD PageFaultCount;
99 DWORD PeakWorkingSetSize;
100 DWORD WorkingSetSize;
101 DWORD QuotaPeakPagedPoolUsage;
102 DWORD QuotaPagedPoolUsage;
103 DWORD QuotaPeakNonPagedPoolUsage;
104 DWORD QuotaNonPagedPoolUsage;
105 DWORD PagefileUsage;
106 DWORD PeakPagefileUsage;
107 DWORD PrivateUsage;
108} PROCESS_MEMORY_COUNTERS_EX,*PPROCESS_MEMORY_COUNTERS_EX;
109
78#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */ 110#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
79#include <sys/socket.h> 111#include <sys/socket.h>
80#undef socket 112#undef socket
@@ -101,6 +133,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
101#include "w32heap.h" 133#include "w32heap.h"
102#include "systime.h" 134#include "systime.h"
103#include "dispextern.h" /* for xstrcasecmp */ 135#include "dispextern.h" /* for xstrcasecmp */
136#include "coding.h" /* for Vlocale_coding_system */
104 137
105/* For serial_configure and serial_open. */ 138/* For serial_configure and serial_open. */
106#include "process.h" 139#include "process.h"
@@ -144,6 +177,16 @@ static BOOL g_b_init_get_file_security;
144static BOOL g_b_init_get_security_descriptor_owner; 177static BOOL g_b_init_get_security_descriptor_owner;
145static BOOL g_b_init_get_security_descriptor_group; 178static BOOL g_b_init_get_security_descriptor_group;
146static BOOL g_b_init_is_valid_sid; 179static BOOL g_b_init_is_valid_sid;
180static BOOL g_b_init_create_toolhelp32_snapshot;
181static BOOL g_b_init_process32_first;
182static BOOL g_b_init_process32_next;
183static BOOL g_b_init_open_thread_token;
184static BOOL g_b_init_impersonate_self;
185static BOOL g_b_init_revert_to_self;
186static BOOL g_b_init_get_process_memory_info;
187static BOOL g_b_init_get_process_working_set_size;
188static BOOL g_b_init_global_memory_status;
189static BOOL g_b_init_global_memory_status_ex;
147 190
148/* 191/*
149 BEGIN: Wrapper functions around OpenProcessToken 192 BEGIN: Wrapper functions around OpenProcessToken
@@ -208,6 +251,35 @@ typedef BOOL (WINAPI * GetSecurityDescriptorGroup_Proc) (
208 LPBOOL lpbGroupDefaulted); 251 LPBOOL lpbGroupDefaulted);
209typedef BOOL (WINAPI * IsValidSid_Proc) ( 252typedef BOOL (WINAPI * IsValidSid_Proc) (
210 PSID sid); 253 PSID sid);
254typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) (
255 DWORD dwFlags,
256 DWORD th32ProcessID);
257typedef BOOL (WINAPI * Process32First_Proc) (
258 HANDLE hSnapshot,
259 LPPROCESSENTRY32 lppe);
260typedef BOOL (WINAPI * Process32Next_Proc) (
261 HANDLE hSnapshot,
262 LPPROCESSENTRY32 lppe);
263typedef BOOL (WINAPI * OpenThreadToken_Proc) (
264 HANDLE ThreadHandle,
265 DWORD DesiredAccess,
266 BOOL OpenAsSelf,
267 PHANDLE TokenHandle);
268typedef BOOL (WINAPI * ImpersonateSelf_Proc) (
269 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel);
270typedef BOOL (WINAPI * RevertToSelf_Proc) (void);
271typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) (
272 HANDLE Process,
273 PPROCESS_MEMORY_COUNTERS ppsmemCounters,
274 DWORD cb);
275typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) (
276 HANDLE hProcess,
277 DWORD * lpMinimumWorkingSetSize,
278 DWORD * lpMaximumWorkingSetSize);
279typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) (
280 LPMEMORYSTATUS lpBuffer);
281typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) (
282 LPMEMORYSTATUSEX lpBuffer);
211 283
212 /* ** A utility function ** */ 284 /* ** A utility function ** */
213static BOOL 285static BOOL
@@ -2557,6 +2629,14 @@ static FILETIME utc_base_ft;
2557static long double utc_base; 2629static long double utc_base;
2558static int init = 0; 2630static int init = 0;
2559 2631
2632static long double
2633convert_time_raw (FILETIME ft)
2634{
2635 return
2636 (long double) ft.dwHighDateTime
2637 * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
2638}
2639
2560static time_t 2640static time_t
2561convert_time (FILETIME ft) 2641convert_time (FILETIME ft)
2562{ 2642{
@@ -2584,12 +2664,10 @@ convert_time (FILETIME ft)
2584 if (CompareFileTime (&ft, &utc_base_ft) < 0) 2664 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2585 return 0; 2665 return 0;
2586 2666
2587 ret = (long double) ft.dwHighDateTime 2667 return (time_t) ((convert_time_raw (ft) - utc_base) * 1e-7L);
2588 * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
2589 ret -= utc_base;
2590 return (time_t) (ret * 1e-7L);
2591} 2668}
2592 2669
2670
2593void 2671void
2594convert_from_time_t (time_t time, FILETIME * pft) 2672convert_from_time_t (time_t time, FILETIME * pft)
2595{ 2673{
@@ -3160,6 +3238,624 @@ utime (const char *name, struct utimbuf *times)
3160 return 0; 3238 return 0;
3161} 3239}
3162 3240
3241
3242/* Support for browsing other processes and their attributes. See
3243 process.c for the Lisp bindings. */
3244
3245/* Helper wrapper functions. */
3246
3247HANDLE WINAPI create_toolhelp32_snapshot(
3248 DWORD Flags,
3249 DWORD Ignored)
3250{
3251 static CreateToolhelp32Snapshot_Proc s_pfn_Create_Toolhelp32_Snapshot = NULL;
3252
3253 if (g_b_init_create_toolhelp32_snapshot == 0)
3254 {
3255 g_b_init_create_toolhelp32_snapshot = 1;
3256 s_pfn_Create_Toolhelp32_Snapshot = (CreateToolhelp32Snapshot_Proc)
3257 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3258 "CreateToolhelp32Snapshot");
3259 }
3260 if (s_pfn_Create_Toolhelp32_Snapshot == NULL)
3261 {
3262 return INVALID_HANDLE_VALUE;
3263 }
3264 return (s_pfn_Create_Toolhelp32_Snapshot (Flags, Ignored));
3265}
3266
3267BOOL WINAPI process32_first(
3268 HANDLE hSnapshot,
3269 LPPROCESSENTRY32 lppe)
3270{
3271 static Process32First_Proc s_pfn_Process32_First = NULL;
3272
3273 if (g_b_init_process32_first == 0)
3274 {
3275 g_b_init_process32_first = 1;
3276 s_pfn_Process32_First = (Process32First_Proc)
3277 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3278 "Process32First");
3279 }
3280 if (s_pfn_Process32_First == NULL)
3281 {
3282 return FALSE;
3283 }
3284 return (s_pfn_Process32_First (hSnapshot, lppe));
3285}
3286
3287BOOL WINAPI process32_next(
3288 HANDLE hSnapshot,
3289 LPPROCESSENTRY32 lppe)
3290{
3291 static Process32Next_Proc s_pfn_Process32_Next = NULL;
3292
3293 if (g_b_init_process32_next == 0)
3294 {
3295 g_b_init_process32_next = 1;
3296 s_pfn_Process32_Next = (Process32Next_Proc)
3297 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3298 "Process32Next");
3299 }
3300 if (s_pfn_Process32_Next == NULL)
3301 {
3302 return FALSE;
3303 }
3304 return (s_pfn_Process32_Next (hSnapshot, lppe));
3305}
3306
3307BOOL WINAPI open_thread_token (
3308 HANDLE ThreadHandle,
3309 DWORD DesiredAccess,
3310 BOOL OpenAsSelf,
3311 PHANDLE TokenHandle)
3312{
3313 static OpenThreadToken_Proc s_pfn_Open_Thread_Token = NULL;
3314 HMODULE hm_advapi32 = NULL;
3315 if (is_windows_9x () == TRUE)
3316 {
3317 SetLastError (ERROR_NOT_SUPPORTED);
3318 return FALSE;
3319 }
3320 if (g_b_init_open_thread_token == 0)
3321 {
3322 g_b_init_open_thread_token = 1;
3323 hm_advapi32 = LoadLibrary ("Advapi32.dll");
3324 s_pfn_Open_Thread_Token =
3325 (OpenThreadToken_Proc) GetProcAddress (hm_advapi32, "OpenThreadToken");
3326 }
3327 if (s_pfn_Open_Thread_Token == NULL)
3328 {
3329 SetLastError (ERROR_NOT_SUPPORTED);
3330 return FALSE;
3331 }
3332 return (
3333 s_pfn_Open_Thread_Token (
3334 ThreadHandle,
3335 DesiredAccess,
3336 OpenAsSelf,
3337 TokenHandle)
3338 );
3339}
3340
3341BOOL WINAPI impersonate_self (
3342 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
3343{
3344 static ImpersonateSelf_Proc s_pfn_Impersonate_Self = NULL;
3345 HMODULE hm_advapi32 = NULL;
3346 if (is_windows_9x () == TRUE)
3347 {
3348 return FALSE;
3349 }
3350 if (g_b_init_impersonate_self == 0)
3351 {
3352 g_b_init_impersonate_self = 1;
3353 hm_advapi32 = LoadLibrary ("Advapi32.dll");
3354 s_pfn_Impersonate_Self =
3355 (ImpersonateSelf_Proc) GetProcAddress (hm_advapi32, "ImpersonateSelf");
3356 }
3357 if (s_pfn_Impersonate_Self == NULL)
3358 {
3359 return FALSE;
3360 }
3361 return s_pfn_Impersonate_Self (ImpersonationLevel);
3362}
3363
3364BOOL WINAPI revert_to_self (void)
3365{
3366 static RevertToSelf_Proc s_pfn_Revert_To_Self = NULL;
3367 HMODULE hm_advapi32 = NULL;
3368 if (is_windows_9x () == TRUE)
3369 {
3370 return FALSE;
3371 }
3372 if (g_b_init_revert_to_self == 0)
3373 {
3374 g_b_init_revert_to_self = 1;
3375 hm_advapi32 = LoadLibrary ("Advapi32.dll");
3376 s_pfn_Revert_To_Self =
3377 (RevertToSelf_Proc) GetProcAddress (hm_advapi32, "RevertToSelf");
3378 }
3379 if (s_pfn_Revert_To_Self == NULL)
3380 {
3381 return FALSE;
3382 }
3383 return s_pfn_Revert_To_Self ();
3384}
3385
3386BOOL WINAPI get_process_memory_info (
3387 HANDLE h_proc,
3388 PPROCESS_MEMORY_COUNTERS mem_counters,
3389 DWORD bufsize)
3390{
3391 static GetProcessMemoryInfo_Proc s_pfn_Get_Process_Memory_Info = NULL;
3392 HMODULE hm_psapi = NULL;
3393 if (is_windows_9x () == TRUE)
3394 {
3395 return FALSE;
3396 }
3397 if (g_b_init_get_process_memory_info == 0)
3398 {
3399 g_b_init_get_process_memory_info = 1;
3400 hm_psapi = LoadLibrary ("Psapi.dll");
3401 if (hm_psapi)
3402 s_pfn_Get_Process_Memory_Info = (GetProcessMemoryInfo_Proc)
3403 GetProcAddress (hm_psapi, "GetProcessMemoryInfo");
3404 }
3405 if (s_pfn_Get_Process_Memory_Info == NULL)
3406 {
3407 return FALSE;
3408 }
3409 return s_pfn_Get_Process_Memory_Info (h_proc, mem_counters, bufsize);
3410}
3411
3412BOOL WINAPI get_process_working_set_size (
3413 HANDLE h_proc,
3414 DWORD *minrss,
3415 DWORD *maxrss)
3416{
3417 static GetProcessWorkingSetSize_Proc
3418 s_pfn_Get_Process_Working_Set_Size = NULL;
3419
3420 if (is_windows_9x () == TRUE)
3421 {
3422 return FALSE;
3423 }
3424 if (g_b_init_get_process_working_set_size == 0)
3425 {
3426 g_b_init_get_process_working_set_size = 1;
3427 s_pfn_Get_Process_Working_Set_Size = (GetProcessWorkingSetSize_Proc)
3428 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3429 "GetProcessWorkingSetSize");
3430 }
3431 if (s_pfn_Get_Process_Working_Set_Size == NULL)
3432 {
3433 return FALSE;
3434 }
3435 return s_pfn_Get_Process_Working_Set_Size (h_proc, minrss, maxrss);
3436}
3437
3438BOOL WINAPI global_memory_status (
3439 MEMORYSTATUS *buf)
3440{
3441 static GlobalMemoryStatus_Proc s_pfn_Global_Memory_Status = NULL;
3442
3443 if (is_windows_9x () == TRUE)
3444 {
3445 return FALSE;
3446 }
3447 if (g_b_init_global_memory_status == 0)
3448 {
3449 g_b_init_global_memory_status = 1;
3450 s_pfn_Global_Memory_Status = (GlobalMemoryStatus_Proc)
3451 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3452 "GlobalMemoryStatus");
3453 }
3454 if (s_pfn_Global_Memory_Status == NULL)
3455 {
3456 return FALSE;
3457 }
3458 return s_pfn_Global_Memory_Status (buf);
3459}
3460
3461BOOL WINAPI global_memory_status_ex (
3462 MEMORYSTATUSEX *buf)
3463{
3464 static GlobalMemoryStatusEx_Proc s_pfn_Global_Memory_Status_Ex = NULL;
3465
3466 if (is_windows_9x () == TRUE)
3467 {
3468 return FALSE;
3469 }
3470 if (g_b_init_global_memory_status_ex == 0)
3471 {
3472 g_b_init_global_memory_status_ex = 1;
3473 s_pfn_Global_Memory_Status_Ex = (GlobalMemoryStatusEx_Proc)
3474 GetProcAddress (GetModuleHandle ("kernel32.dll"),
3475 "GlobalMemoryStatusEx");
3476 }
3477 if (s_pfn_Global_Memory_Status_Ex == NULL)
3478 {
3479 return FALSE;
3480 }
3481 return s_pfn_Global_Memory_Status_Ex (buf);
3482}
3483
3484Lisp_Object
3485w32_list_system_processes ()
3486{
3487 struct gcpro gcpro1;
3488 Lisp_Object proclist = Qnil;
3489 HANDLE h_snapshot;
3490
3491 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
3492
3493 if (h_snapshot != INVALID_HANDLE_VALUE)
3494 {
3495 PROCESSENTRY32 proc_entry;
3496 DWORD proc_id;
3497 BOOL res;
3498
3499 GCPRO1 (proclist);
3500
3501 proc_entry.dwSize = sizeof (PROCESSENTRY32);
3502 for (res = process32_first (h_snapshot, &proc_entry); res;
3503 res = process32_next (h_snapshot, &proc_entry))
3504 {
3505 proc_id = proc_entry.th32ProcessID;
3506 proclist = Fcons (make_fixnum_or_float (proc_id), proclist);
3507 }
3508
3509 CloseHandle (h_snapshot);
3510 UNGCPRO;
3511 proclist = Fnreverse (proclist);
3512 }
3513
3514 return proclist;
3515}
3516
3517static int
3518enable_privilege (LPCTSTR priv_name, BOOL enable_p, TOKEN_PRIVILEGES *old_priv)
3519{
3520 TOKEN_PRIVILEGES priv;
3521 DWORD priv_size = sizeof (priv);
3522 DWORD opriv_size = sizeof (*old_priv);
3523 HANDLE h_token = NULL;
3524 HANDLE h_thread = GetCurrentThread ();
3525 int ret_val = 0;
3526 BOOL res;
3527
3528 res = open_thread_token (h_thread,
3529 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
3530 FALSE, &h_token);
3531 if (!res && GetLastError () == ERROR_NO_TOKEN)
3532 {
3533 if (impersonate_self (SecurityImpersonation))
3534 res = open_thread_token (h_thread,
3535 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
3536 FALSE, &h_token);
3537 }
3538 if (res)
3539 {
3540 priv.PrivilegeCount = 1;
3541 priv.Privileges[0].Attributes = enable_p ? SE_PRIVILEGE_ENABLED : 0;
3542 LookupPrivilegeValue (NULL, priv_name, &priv.Privileges[0].Luid);
3543 if (AdjustTokenPrivileges (h_token, FALSE, &priv, priv_size,
3544 old_priv, &opriv_size)
3545 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
3546 ret_val = 1;
3547 }
3548 if (h_token)
3549 CloseHandle (h_token);
3550
3551 return ret_val;
3552}
3553
3554static int
3555restore_privilege (TOKEN_PRIVILEGES *priv)
3556{
3557 DWORD priv_size = sizeof (*priv);
3558 HANDLE h_token = NULL;
3559 int ret_val = 0;
3560
3561 if (open_thread_token (GetCurrentThread (),
3562 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
3563 FALSE, &h_token))
3564 {
3565 if (AdjustTokenPrivileges (h_token, FALSE, priv, priv_size, NULL, NULL)
3566 && GetLastError () != ERROR_NOT_ALL_ASSIGNED)
3567 ret_val = 1;
3568 }
3569 if (h_token)
3570 CloseHandle (h_token);
3571
3572 return ret_val;
3573}
3574
3575static Lisp_Object
3576ltime (time_sec, time_usec)
3577 long time_sec, time_usec;
3578{
3579 return list3 (make_number ((time_sec >> 16) & 0xffff),
3580 make_number (time_sec & 0xffff),
3581 make_number (time_usec));
3582}
3583
3584static int
3585process_times (h_proc, ctime, etime, stime, utime, pcpu)
3586 HANDLE h_proc;
3587 Lisp_Object *ctime, *etime, *stime, *utime;
3588 double *pcpu;
3589{
3590 FILETIME ft_creation, ft_exit, ft_kernel, ft_user, ft_current;
3591 long ctime_sec, ctime_usec, stime_sec, stime_usec, utime_sec, utime_usec;
3592 long etime_sec, etime_usec;
3593 long double tem1, tem2, tem;
3594
3595 if (!h_proc
3596 || !get_process_times_fn
3597 || !(*get_process_times_fn)(h_proc, &ft_creation, &ft_exit,
3598 &ft_kernel, &ft_user))
3599 return 0;
3600
3601 GetSystemTimeAsFileTime (&ft_current);
3602
3603 tem1 = convert_time_raw (ft_kernel) * 0.1L;
3604 stime_usec = fmodl (tem1, 1000000.0L);
3605 stime_sec = tem1 * 0.000001L;
3606 *stime = ltime (stime_sec, stime_usec);
3607 tem2 = convert_time_raw (ft_user) * 0.1L;
3608 utime_usec = fmodl (tem2, 1000000.0L);
3609 utime_sec = tem2 * 0.000001L;
3610 *utime = ltime (utime_sec, utime_usec);
3611 tem = (convert_time_raw (ft_creation) - utc_base) * 0.1L;
3612 ctime_usec = fmodl (tem, 1000000.0L);
3613 ctime_sec = tem * 0.000001L;
3614 *ctime = ltime (ctime_sec, ctime_usec);
3615 tem = (convert_time_raw (ft_current) - utc_base) * 0.1L - tem;
3616 etime_usec = fmodl (tem, 1000000.0L);
3617 etime_sec = tem * 0.000001L;
3618 *etime = ltime (etime_sec, etime_usec);
3619
3620 *pcpu = 100.0 * (tem1 + tem2) / tem;
3621}
3622
3623Lisp_Object
3624w32_system_process_attributes (pid)
3625 Lisp_Object pid;
3626{
3627 struct gcpro gcpro1, gcpro2, gcpro3;
3628 Lisp_Object attrs = Qnil;
3629 Lisp_Object cmd_str, decoded_cmd, tem;
3630 HANDLE h_snapshot, h_proc;
3631 DWORD proc_id;
3632 char uname[UNLEN+1], gname[GNLEN+1], domain[1025];
3633 DWORD ulength = sizeof (uname), dlength = sizeof (domain), trash;
3634 DWORD glength = sizeof (gname);
3635 HANDLE token = NULL;
3636 SID_NAME_USE user_type;
3637 unsigned char buf[1024];
3638 TOKEN_USER user_token;
3639 TOKEN_PRIMARY_GROUP group_token;
3640 int euid;
3641 int egid;
3642 DWORD sess;
3643 PROCESS_MEMORY_COUNTERS mem;
3644 PROCESS_MEMORY_COUNTERS_EX mem_ex;
3645 DWORD minrss, maxrss;
3646 MEMORYSTATUS memst;
3647 MEMORYSTATUSEX memstex;
3648 double totphys = 0.0;
3649 Lisp_Object ctime, stime, utime, etime;
3650 double pcpu;
3651
3652 CHECK_NUMBER_OR_FLOAT (pid);
3653 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3654
3655 h_snapshot = create_toolhelp32_snapshot (TH32CS_SNAPPROCESS, 0);
3656
3657 GCPRO3 (attrs, decoded_cmd, tem);
3658
3659 if (h_snapshot != INVALID_HANDLE_VALUE)
3660 {
3661 PROCESSENTRY32 pe;
3662 BOOL res;
3663
3664 pe.dwSize = sizeof (PROCESSENTRY32);
3665 for (res = process32_first (h_snapshot, &pe); res;
3666 res = process32_next (h_snapshot, &pe))
3667 {
3668 if (proc_id == pe.th32ProcessID)
3669 {
3670 if (proc_id == 0)
3671 decoded_cmd = build_string ("Idle");
3672 else
3673 {
3674 /* Decode the command name from locale-specific
3675 encoding. */
3676 cmd_str = make_unibyte_string (pe.szExeFile,
3677 strlen (pe.szExeFile));
3678 decoded_cmd =
3679 code_convert_string_norecord (cmd_str,
3680 Vlocale_coding_system, 0);
3681 }
3682 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3683 attrs = Fcons (Fcons (Qppid,
3684 make_fixnum_or_float (pe.th32ParentProcessID)),
3685 attrs);
3686 attrs = Fcons (Fcons (Qpri, make_number (pe.pcPriClassBase)),
3687 attrs);
3688 attrs = Fcons (Fcons (Qthcount,
3689 make_fixnum_or_float (pe.cntThreads)),
3690 attrs);
3691 break;
3692 }
3693 }
3694
3695 CloseHandle (h_snapshot);
3696 }
3697
3698 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
3699 FALSE, proc_id);
3700 /* If we were denied a handle to the process, try again after
3701 enabling the SeDebugPrivilege in our process. */
3702 if (!h_proc)
3703 {
3704 TOKEN_PRIVILEGES priv_current;
3705
3706 if (enable_privilege (SE_DEBUG_NAME, TRUE, &priv_current))
3707 {
3708 h_proc = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
3709 FALSE, proc_id);
3710 restore_privilege (&priv_current);
3711 revert_to_self ();
3712 }
3713 }
3714 if (h_proc
3715 && open_process_token (h_proc, TOKEN_QUERY, &token)
3716 && get_token_information (token, TokenUser,
3717 (PVOID)buf, sizeof (buf), &trash)
3718 && (memcpy (&user_token, buf, sizeof (user_token)),
3719 lookup_account_sid (NULL, user_token.User.Sid, uname, &ulength,
3720 domain, &dlength, &user_type)))
3721 {
3722 /* Determine a reasonable euid and gid values. */
3723 if (xstrcasecmp ("administrator", uname) == 0)
3724 {
3725 euid = 500; /* well-known Administrator uid */
3726 egid = 513; /* well-known None gid */
3727 }
3728 else
3729 {
3730 /* Use the last sub-authority value of the RID, the relative
3731 portion of the SID, as user/group ID. */
3732 euid = get_rid (user_token.User.Sid);
3733
3734 /* Get group id and name. */
3735 if (get_token_information (token, TokenPrimaryGroup,
3736 (PVOID)buf, sizeof (buf), &trash))
3737 {
3738 memcpy (&group_token, buf, sizeof (group_token));
3739 egid = get_rid (group_token.PrimaryGroup);
3740 dlength = sizeof (domain);
3741 lookup_account_sid (NULL, group_token.PrimaryGroup,
3742 gname, &glength, NULL, &dlength,
3743 &user_type);
3744 }
3745 else
3746 egid = euid;
3747 }
3748 }
3749 else if (!is_windows_9x ())
3750 {
3751 /* We couldn't open the process token, presumably because of
3752 insufficient access rights. Assume this process is run by
3753 the system. */
3754 strcpy (uname, "SYSTEM");
3755 strcpy (gname, "None");
3756 euid = 18; /* SYSTEM */
3757 egid = 513; /* None */
3758 glength = strlen (gname);
3759 ulength = strlen (uname);
3760 }
3761 /* If we are running under Windows 9X, where security calls are not
3762 supported, we assume all processes are run by the current
3763 user. */
3764 else if (GetUserName (uname, &ulength))
3765 {
3766 if (xstrcasecmp ("administrator", uname) == 0)
3767 euid = 0;
3768 else
3769 euid = 123;
3770 egid = euid;
3771 strcpy (gname, "None");
3772 glength = strlen (gname);
3773 ulength = strlen (uname);
3774 }
3775 else
3776 {
3777 euid = 123;
3778 egid = 123;
3779 strcpy (uname, "administrator");
3780 ulength = strlen (uname);
3781 strcpy (gname, "None");
3782 glength = strlen (gname);
3783 }
3784 if (token)
3785 CloseHandle (token);
3786
3787 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (euid)), attrs);
3788 tem = make_unibyte_string (uname, ulength);
3789 attrs = Fcons (Fcons (Quser,
3790 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
3791 attrs);
3792 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (egid)), attrs);
3793 tem = make_unibyte_string (gname, glength);
3794 attrs = Fcons (Fcons (Qgroup,
3795 code_convert_string_norecord (tem, Vlocale_coding_system, 0)),
3796 attrs);
3797
3798 if (global_memory_status_ex (&memstex))
3799 totphys = memstex.ullTotalPhys / 1024.0;
3800 else if (global_memory_status (&memst))
3801 totphys = memst.dwTotalPhys / 1024.0;
3802
3803 if (h_proc
3804 && get_process_memory_info (h_proc, (PROCESS_MEMORY_COUNTERS *)&mem_ex,
3805 sizeof (mem_ex)))
3806 {
3807 DWORD rss = mem_ex.WorkingSetSize / 1024;
3808
3809 attrs = Fcons (Fcons (Qmajflt,
3810 make_fixnum_or_float (mem_ex.PageFaultCount)),
3811 attrs);
3812 attrs = Fcons (Fcons (Qvsize,
3813 make_fixnum_or_float (mem_ex.PrivateUsage / 1024)),
3814 attrs);
3815 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
3816 if (totphys)
3817 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
3818 }
3819 else if (h_proc
3820 && get_process_memory_info (h_proc, &mem, sizeof (mem)))
3821 {
3822 DWORD rss = mem_ex.WorkingSetSize / 1024;
3823
3824 attrs = Fcons (Fcons (Qmajflt,
3825 make_fixnum_or_float (mem.PageFaultCount)),
3826 attrs);
3827 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (rss)), attrs);
3828 if (totphys)
3829 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
3830 }
3831 else if (h_proc
3832 && get_process_working_set_size (h_proc, &minrss, &maxrss))
3833 {
3834 DWORD rss = maxrss / 1024;
3835
3836 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (maxrss / 1024)), attrs);
3837 if (totphys)
3838 attrs = Fcons (Fcons (Qpmem, make_float (100. * rss / totphys)), attrs);
3839 }
3840
3841 if (process_times (h_proc, &ctime, &etime, &stime, &utime, &pcpu))
3842 {
3843 attrs = Fcons (Fcons (Qutime, utime), attrs);
3844 attrs = Fcons (Fcons (Qstime, stime), attrs);
3845 attrs = Fcons (Fcons (Qstart, ctime), attrs);
3846 attrs = Fcons (Fcons (Qetime, etime), attrs);
3847 attrs = Fcons (Fcons (Qpcpu, make_float (pcpu)), attrs);
3848 }
3849
3850 /* FIXME: Retrieve command line by walking the PEB of the process. */
3851
3852 if (h_proc)
3853 CloseHandle (h_proc);
3854 UNGCPRO;
3855 return attrs;
3856}
3857
3858
3163#ifdef HAVE_SOCKETS 3859#ifdef HAVE_SOCKETS
3164 3860
3165/* Wrappers for winsock functions to map between our file descriptors 3861/* Wrappers for winsock functions to map between our file descriptors
@@ -4717,6 +5413,16 @@ globals_of_w32 ()
4717 g_b_init_get_security_descriptor_owner = 0; 5413 g_b_init_get_security_descriptor_owner = 0;
4718 g_b_init_get_security_descriptor_group = 0; 5414 g_b_init_get_security_descriptor_group = 0;
4719 g_b_init_is_valid_sid = 0; 5415 g_b_init_is_valid_sid = 0;
5416 g_b_init_create_toolhelp32_snapshot = 0;
5417 g_b_init_process32_first = 0;
5418 g_b_init_process32_next = 0;
5419 g_b_init_open_thread_token = 0;
5420 g_b_init_impersonate_self = 0;
5421 g_b_init_revert_to_self = 0;
5422 g_b_init_get_process_memory_info = 0;
5423 g_b_init_get_process_working_set_size = 0;
5424 g_b_init_global_memory_status = 0;
5425 g_b_init_global_memory_status_ex = 0;
4720 /* The following sets a handler for shutdown notifications for 5426 /* The following sets a handler for shutdown notifications for
4721 console apps. This actually applies to Emacs in both console and 5427 console apps. This actually applies to Emacs in both console and
4722 GUI modes, since we had to fool windows into thinking emacs is a 5428 GUI modes, since we had to fool windows into thinking emacs is a