diff options
| author | Eli Zaretskii | 2008-08-09 17:53:00 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2008-08-09 17:53:00 +0000 |
| commit | 7c80d5ec06b0934d72fc278405d0a3a1895bbe6e (patch) | |
| tree | 8924e56bdb55f3f50345019457a333c861b6f33a /src | |
| parent | a96a1d43db8cf18fc4d10992f1f96ad94e5aba13 (diff) | |
| download | emacs-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.c | 714 |
1 files changed, 710 insertions, 4 deletions
| @@ -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. */ | ||
| 77 | typedef 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. */ | ||
| 96 | typedef 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; | |||
| 144 | static BOOL g_b_init_get_security_descriptor_owner; | 177 | static BOOL g_b_init_get_security_descriptor_owner; |
| 145 | static BOOL g_b_init_get_security_descriptor_group; | 178 | static BOOL g_b_init_get_security_descriptor_group; |
| 146 | static BOOL g_b_init_is_valid_sid; | 179 | static BOOL g_b_init_is_valid_sid; |
| 180 | static BOOL g_b_init_create_toolhelp32_snapshot; | ||
| 181 | static BOOL g_b_init_process32_first; | ||
| 182 | static BOOL g_b_init_process32_next; | ||
| 183 | static BOOL g_b_init_open_thread_token; | ||
| 184 | static BOOL g_b_init_impersonate_self; | ||
| 185 | static BOOL g_b_init_revert_to_self; | ||
| 186 | static BOOL g_b_init_get_process_memory_info; | ||
| 187 | static BOOL g_b_init_get_process_working_set_size; | ||
| 188 | static BOOL g_b_init_global_memory_status; | ||
| 189 | static 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); |
| 209 | typedef BOOL (WINAPI * IsValidSid_Proc) ( | 252 | typedef BOOL (WINAPI * IsValidSid_Proc) ( |
| 210 | PSID sid); | 253 | PSID sid); |
| 254 | typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_Proc) ( | ||
| 255 | DWORD dwFlags, | ||
| 256 | DWORD th32ProcessID); | ||
| 257 | typedef BOOL (WINAPI * Process32First_Proc) ( | ||
| 258 | HANDLE hSnapshot, | ||
| 259 | LPPROCESSENTRY32 lppe); | ||
| 260 | typedef BOOL (WINAPI * Process32Next_Proc) ( | ||
| 261 | HANDLE hSnapshot, | ||
| 262 | LPPROCESSENTRY32 lppe); | ||
| 263 | typedef BOOL (WINAPI * OpenThreadToken_Proc) ( | ||
| 264 | HANDLE ThreadHandle, | ||
| 265 | DWORD DesiredAccess, | ||
| 266 | BOOL OpenAsSelf, | ||
| 267 | PHANDLE TokenHandle); | ||
| 268 | typedef BOOL (WINAPI * ImpersonateSelf_Proc) ( | ||
| 269 | SECURITY_IMPERSONATION_LEVEL ImpersonationLevel); | ||
| 270 | typedef BOOL (WINAPI * RevertToSelf_Proc) (void); | ||
| 271 | typedef BOOL (WINAPI * GetProcessMemoryInfo_Proc) ( | ||
| 272 | HANDLE Process, | ||
| 273 | PPROCESS_MEMORY_COUNTERS ppsmemCounters, | ||
| 274 | DWORD cb); | ||
| 275 | typedef BOOL (WINAPI * GetProcessWorkingSetSize_Proc) ( | ||
| 276 | HANDLE hProcess, | ||
| 277 | DWORD * lpMinimumWorkingSetSize, | ||
| 278 | DWORD * lpMaximumWorkingSetSize); | ||
| 279 | typedef BOOL (WINAPI * GlobalMemoryStatus_Proc) ( | ||
| 280 | LPMEMORYSTATUS lpBuffer); | ||
| 281 | typedef BOOL (WINAPI * GlobalMemoryStatusEx_Proc) ( | ||
| 282 | LPMEMORYSTATUSEX lpBuffer); | ||
| 211 | 283 | ||
| 212 | /* ** A utility function ** */ | 284 | /* ** A utility function ** */ |
| 213 | static BOOL | 285 | static BOOL |
| @@ -2557,6 +2629,14 @@ static FILETIME utc_base_ft; | |||
| 2557 | static long double utc_base; | 2629 | static long double utc_base; |
| 2558 | static int init = 0; | 2630 | static int init = 0; |
| 2559 | 2631 | ||
| 2632 | static long double | ||
| 2633 | convert_time_raw (FILETIME ft) | ||
| 2634 | { | ||
| 2635 | return | ||
| 2636 | (long double) ft.dwHighDateTime | ||
| 2637 | * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime; | ||
| 2638 | } | ||
| 2639 | |||
| 2560 | static time_t | 2640 | static time_t |
| 2561 | convert_time (FILETIME ft) | 2641 | convert_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 | |||
| 2593 | void | 2671 | void |
| 2594 | convert_from_time_t (time_t time, FILETIME * pft) | 2672 | convert_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 | |||
| 3247 | HANDLE 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 | |||
| 3267 | BOOL 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 | |||
| 3287 | BOOL 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 | |||
| 3307 | BOOL 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 | |||
| 3341 | BOOL 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 | |||
| 3364 | BOOL 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 | |||
| 3386 | BOOL 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 | |||
| 3412 | BOOL 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 | |||
| 3438 | BOOL 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 | |||
| 3461 | BOOL 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 | |||
| 3484 | Lisp_Object | ||
| 3485 | w32_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 | |||
| 3517 | static int | ||
| 3518 | enable_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 | |||
| 3554 | static int | ||
| 3555 | restore_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 | |||
| 3575 | static Lisp_Object | ||
| 3576 | ltime (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 | |||
| 3584 | static int | ||
| 3585 | process_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 | |||
| 3623 | Lisp_Object | ||
| 3624 | w32_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 |