diff options
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 45 | ||||
-rw-r--r-- | winsup/cygwin/autoload.cc | 2 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 19 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_proc.cc | 237 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_process.cc | 522 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_registry.cc | 7 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_virtual.cc | 19 | ||||
-rw-r--r-- | winsup/cygwin/ntdll.h | 210 | ||||
-rw-r--r-- | winsup/cygwin/wincap.cc | 11 | ||||
-rw-r--r-- | winsup/cygwin/wincap.h | 2 |
10 files changed, 1001 insertions, 73 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7584ed1..1bbffbd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,4 +1,47 @@ -2002-05-09 Christopher Faylor <cgf@redhat.com> +2002-05-10 Christopher January <chris@atomice.net> + + * autoload.cc: Add dynamic load statements for + 'ZwQueryInformationProcess' and 'ZwQueryVirtualMemory'. + * fhandler.h: Change type of bufalloc and filesize members of + fhandler_virtual from int to size_t. Change type of position member + from __off32_t to __off64_t. Add new fileid member to fhandler_virtual + class. Make seekdir take an __off64_t argument. Make lseek take an + __off64_t argument. Add fill_filebuf method to fhandler_virtual. Add + fill_filebuf method to fhandler_proc. Add fill_filebuf method to + fhandler_registry. Add fill_filebuf method to fhandler_process. Add + saved_pid and saved_p members to fhandler_process. + * fhandler_proc.cc (proc_listing_array): Add 'loadavg', 'meminfo', and 'stat'. + (proc_fhandlers array): Ditto. + (fhandler_proc::open): Use fill_filebuf to flesh out the file contents. + (fhandler_proc::fill_filebuf): New method. + (fhandler_proc::format_proc_meminfo): Ditto. + (fhandler_proc::format_proc_stat): Ditto. + (fhandler_proc::format_proc_uptime): Ditto. + * fhandler_process.cc (process_listing): Add 'stat' and 'statm'. + (fhandler_process::fstat): Find the _pinfo structure for the process + named in the filename. Return ENOENT if the process is no longer + around. Set the gid and uid fields of the stat structure. + (fhandler_process::open): Store pid and pointer to _pinfo structure in + saved_pid and saved_p respectively. Use fill_filebuf to flesh out file + contents. + (fhandler_proc::fill_filebuf): New method. + (format_process_stat): New function. + (format_process_status): Ditto. + (format_process_statm): Ditto. + (get_process_state): Ditto. + (get_mem_values): Ditto. + * fhandler_registry.cc (fhandler_registry::seekdir): Change argument + type from __off32_t to __off64_t. + (fhandler_registry::fill_filebuf): New method. + * fhandler_virtual.cc (fhandler_virtual::seekdir): Change argument type + from __off32_t to __off64_t. + (fhandler_virtual::lseek): Ditto. + (fhandler_virtual::fill_filebuf): New method. + (fhandler_virtual::fhandler_virtual): Initialise fileid to -1. + * wincap.cc: Set flag has_process_io_counters appropriately. + * wincap.h: Add flag has_process_io_counters. + +2002-05-09 Christopher Faylor <cgf@redhat.com> * syscalls.cc (_write): Change error to EBADF if attempt to write to a non-writable fd. diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 3a82e38..6592ef2 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -381,6 +381,8 @@ LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1) LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1) LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1) LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1) +LoadDLLfuncEx (ZwQueryInformationProcess, 20, ntdll, 1) +LoadDLLfuncEx (ZwQueryVirtualMemory, 24, ntdll, 1) LoadDLLfuncEx (GetProcessMemoryInfo, 12, psapi, 1) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index aa0b6cc..1a48073 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1043,8 +1043,9 @@ class fhandler_virtual : public fhandler_base { protected: char *filebuf; - int bufalloc, filesize; - __off32_t position; + size_t bufalloc, filesize; + __off64_t position; + int fileid; // unique within each class public: fhandler_virtual (DWORD devtype); @@ -1053,16 +1054,17 @@ class fhandler_virtual : public fhandler_base virtual int exists(const char *path); DIR *opendir (path_conv& pc); __off64_t telldir (DIR *); - void seekdir (DIR *, __off32_t); + void seekdir (DIR *, __off64_t); void rewinddir (DIR *); int closedir (DIR *); int write (const void *ptr, size_t len); int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3))); - __off64_t lseek (__off32_t, int); + __off64_t lseek (__off64_t, int); int dup (fhandler_base * child); int open (path_conv *, int flags, mode_t mode = 0); int close (void); int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3))); + virtual void fill_filebuf (); }; class fhandler_proc: public fhandler_virtual @@ -1076,6 +1078,7 @@ class fhandler_proc: public fhandler_virtual int open (path_conv *real_path, int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3))); + void fill_filebuf (); }; class fhandler_registry: public fhandler_proc @@ -1085,23 +1088,29 @@ class fhandler_registry: public fhandler_proc int exists(const char *path); struct dirent *readdir (DIR *); __off64_t telldir (DIR *); - void seekdir (DIR *, __off32_t); + void seekdir (DIR *, __off64_t); void rewinddir (DIR *); int closedir (DIR *); int open (path_conv *real_path, int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3))); HKEY open_key(const char *name, REGSAM access = KEY_READ, bool isValue = false); + void fill_filebuf (); }; +struct _pinfo; class fhandler_process: public fhandler_proc { + private: + pid_t saved_pid; + _pinfo *saved_p; public: fhandler_process (); int exists(const char *path); struct dirent *readdir (DIR *); int open (path_conv *real_path, int flags, mode_t mode = 0); int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3))); + void fill_filebuf (); }; typedef union diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc index 3d49469..60e9578 100644 --- a/winsup/cygwin/fhandler_proc.cc +++ b/winsup/cygwin/fhandler_proc.cc @@ -14,6 +14,7 @@ details. */ #include <unistd.h> #include <stdlib.h> #include <sys/cygwin.h> +#include <ntdef.h> #include "cygerrno.h" #include "security.h" #include "fhandler.h" @@ -24,20 +25,27 @@ details. */ #include "cygheap.h" #include <assert.h> #include <sys/utsname.h> +#include "ntdll.h" #define _COMPILING_NEWLIB #include <dirent.h> /* offsets in proc_listing */ -static const int PROC_REGISTRY = 2; // /proc/registry -static const int PROC_VERSION = 3; // /proc/version -static const int PROC_UPTIME = 4; // /proc/uptime +static const int PROC_LOADAVG = 2; // /proc/loadavg +static const int PROC_MEMINFO = 3; // /proc/meminfo +static const int PROC_REGISTRY = 4; // /proc/registry +static const int PROC_STAT = 5; // /proc/stat +static const int PROC_VERSION = 6; // /proc/version +static const int PROC_UPTIME = 7; // /proc/uptime /* names of objects in /proc */ static const char *proc_listing[] = { ".", "..", + "loadavg", + "meminfo", "registry", + "stat", "version", "uptime", NULL @@ -48,11 +56,14 @@ static const int PROC_LINK_COUNT = (sizeof(proc_listing) / sizeof(const char *)) /* FH_PROC in the table below means the file/directory is handles by * fhandler_proc. */ -static const DWORD proc_fhandlers[] = { +static const DWORD proc_fhandlers[PROC_LINK_COUNT] = { + FH_PROC, + FH_PROC, FH_PROC, FH_PROC, FH_REGISTRY, FH_PROC, + FH_PROC, FH_PROC }; @@ -60,6 +71,10 @@ static const DWORD proc_fhandlers[] = { const char proc[] = "/proc"; const int proc_len = sizeof (proc) - 1; +static off_t format_proc_meminfo (char *destbuf, size_t maxsize); +static off_t format_proc_stat (char *destbuf, size_t maxsize); +static off_t format_proc_uptime (char *destbuf, size_t maxsize); + /* auxillary function that returns the fhandler associated with the given path * this is where it would be nice to have pattern matching in C - polymorphism * just doesn't cut it @@ -291,44 +306,214 @@ fhandler_proc::open (path_conv *pc, int flags, mode_t mode) res = 0; goto out; } - switch (proc_file_no) + + fileid = proc_file_no; + fill_filebuf (); + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_open_status (); + set_flags (flags); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} + +void +fhandler_proc::fill_filebuf () +{ + switch (fileid) { case PROC_VERSION: { + if (!filebuf) + { struct utsname uts_name; uname (&uts_name); - filesize = bufalloc = strlen (uts_name.sysname) + 1 + - strlen (uts_name.release) + 1 + strlen (uts_name.version) + 2; + bufalloc = strlen (uts_name.sysname) + 1 + strlen (uts_name.release) + + 1 + strlen (uts_name.version) + 2; filebuf = (char *) cmalloc (HEAP_BUF, bufalloc); - __small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname, + filesize = __small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname, uts_name.release, uts_name.version); + } break; } case PROC_UPTIME: { - /* GetTickCount() wraps after 49 days - on WinNT/2000/XP, should use - * perfomance counters but I don't know Redhat's policy on - * NT only dependancies. + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 80); + filesize = format_proc_uptime (filebuf, bufalloc); + break; + } + case PROC_STAT: + { + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048); + filesize = format_proc_stat (filebuf, bufalloc); + break; + } + case PROC_LOADAVG: + { + /* + * not really supported - Windows doesn't keep track of these values + * Windows 95/98/me does have the KERNEL/CPUUsage performance counter + * which is similar. */ - DWORD ticks = GetTickCount (); - filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40); - __small_sprintf (filebuf, "%d.%02d\n", ticks / 1000, - (ticks / 10) % 100); - filesize = strlen (filebuf); + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 16); + filesize = __small_sprintf (filebuf, "%u.%02u %u.%02u %u.%02u\n", + 0, 0, 0, 0, 0, 0); + break; + } + case PROC_MEMINFO: + { + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048); + filesize = format_proc_meminfo (filebuf, bufalloc); break; } } +} - if (flags & O_APPEND) - position = filesize; +static +off_t +format_proc_meminfo (char *destbuf, size_t maxsize) +{ + unsigned long mem_total = 0UL, mem_free = 0UL, swap_total = 0UL, + swap_free = 0UL; + MEMORYSTATUS memory_status; + GlobalMemoryStatus (&memory_status); + mem_total = memory_status.dwTotalPhys; + mem_free = memory_status.dwAvailPhys; + swap_total = memory_status.dwTotalPageFile; + swap_free = memory_status.dwAvailPageFile; + return __small_sprintf (destbuf, " total: used: free:\n" + "Mem: %10lu %10lu %10lu\n" + "Swap: %10lu %10lu %10lu\n" + "MemTotal: %10lu kB\n" + "MemFree: %10lu kB\n" + "MemShared: 0 kB\n" + "HighTotal: 0 kB\n" + "HighFree: 0 kB\n" + "LowTotal: %10lu kB\n" + "LowFree: %10lu kB\n" + "SwapTotal: %10lu kB\n" + "SwapFree: %10lu kB\n", + mem_total, mem_total - mem_free, mem_free, + swap_total, swap_total - swap_free, swap_free, + mem_total >> 10, mem_free >> 10, + mem_total >> 10, mem_free >> 10, + swap_total >> 10, swap_free >> 10); +} + +static +off_t +format_proc_uptime (char *destbuf, size_t maxsize) +{ + unsigned long long uptime = 0ULL, idle_time = 0ULL; + SYSTEM_PROCESSOR_TIMES spt; + + NTSTATUS ret = ZwQuerySystemInformation (SystemProcessorTimes, (PVOID) &spt, + sizeof spt, NULL); + if (!ret && GetLastError () == ERROR_PROC_NOT_FOUND) + uptime = GetTickCount() / 10; + else if (ret != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + debug_printf("NtQuerySystemInformation: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + return 0; + } else - position = 0; + { + idle_time = spt.IdleTime.QuadPart / 100000ULL; + uptime = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart + + spt.IdleTime.QuadPart + spt.UserTime.QuadPart + + spt.DpcTime.QuadPart) / 100000ULL; + } -success: - res = 1; - set_open_status (); - set_flags (flags); -out: - syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); - return res; + return __small_sprintf (destbuf, "%U.%02u %U.%02u\n", + uptime / 100, long (uptime % 100), + idle_time / 100, long (idle_time % 100)); +} + +static +off_t +format_proc_stat (char *destbuf, size_t maxsize) +{ + unsigned long long user_time = 0ULL, kernel_time = 0ULL, idle_time = 0ULL; + unsigned long pages_in = 0UL, pages_out = 0UL, interrupt_count = 0UL, + context_switches = 0UL, swap_in = 0UL, swap_out = 0UL; + time_t boot_time = 0; + + if (wincap.is_winnt ()) + { + NTSTATUS ret; + SYSTEM_PROCESSOR_TIMES spt; + SYSTEM_PERFORMANCE_INFORMATION spi; + SYSTEM_TIME_OF_DAY_INFORMATION stodi; + ret = ZwQuerySystemInformation (SystemProcessorTimes, + (PVOID) &spt, + sizeof spt, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQuerySystemInformation (SystemPerformanceInformation, + (PVOID) &spi, + sizeof spi, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQuerySystemInformation (SystemTimeOfDayInformation, + (PVOID) &stodi, + sizeof stodi, NULL); + if (ret != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + debug_printf("NtQuerySystemInformation: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + return 0; + } + kernel_time = (spt.KernelTime.QuadPart + spt.InterruptTime.QuadPart + spt.DpcTime.QuadPart) / 100000ULL; + user_time = spt.UserTime.QuadPart / 100000ULL; + idle_time = spt.IdleTime.QuadPart / 100000ULL; + interrupt_count = spt.InterruptCount; + pages_in = spi.PagesRead; + pages_out = spi.PagefilePagesWritten + spi.MappedFilePagesWritten; + /* + * Note: there is no distinction made in this structure between pages + * read from the page file and pages read from mapped files, but there + * is such a distinction made when it comes to writing. Goodness knows + * why. The value of swap_in, then, will obviously be wrong but its our + * best guess. + */ + swap_in = spi.PagesRead; + swap_out = spi.PagefilePagesWritten; + context_switches = spi.ContextSwitches; + boot_time = to_time_t ((FILETIME *) &stodi.BootTime.QuadPart); + } + /* + * else + * { + * There are only two relevant performance counters on Windows 95/98/me, + * VMM/cPageIns and VMM/cPageOuts. The extra effort needed to read these + * counters is by no means worth it. + * } + */ + return __small_sprintf (destbuf, "cpu %U %U %U %U\n" + "page %u %u\n" + "swap %u %u\n" + "intr %u\n" + "ctxt %u\n" + "btime %u\n", + user_time, 0ULL, + kernel_time, idle_time, + pages_in, pages_out, + swap_in, swap_out, + interrupt_count, + context_switches, + boot_time); } diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc index 7f68d4a..f374d4d 100644 --- a/winsup/cygwin/fhandler_process.cc +++ b/winsup/cygwin/fhandler_process.cc @@ -14,6 +14,7 @@ details. */ #include <unistd.h> #include <stdlib.h> #include <sys/cygwin.h> +#include <ntdef.h> #include "cygerrno.h" #include "security.h" #include "fhandler.h" @@ -23,6 +24,7 @@ details. */ #include "shared_info.h" #include "dtable.h" #include "cygheap.h" +#include "ntdll.h" #include <assert.h> #define _COMPILING_NEWLIB @@ -38,6 +40,8 @@ static const int PROCESS_GID = 8; static const int PROCESS_PGID = 9; static const int PROCESS_SID = 10; static const int PROCESS_CTTY = 11; +static const int PROCESS_STAT = 12; +static const int PROCESS_STATM = 13; static const char *process_listing[] = { ".", @@ -52,11 +56,20 @@ static const char *process_listing[] = { "pgid", "sid", "ctty", + "stat", + "statm", NULL }; static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1; +static off_t format_process_stat (_pinfo *p, char *destbuf, size_t maxsize); +static off_t format_process_status (_pinfo *p, char *destbuf, size_t maxsize); +static off_t format_process_statm (_pinfo *p, char *destbuf, size_t maxsize); +static int get_process_state (DWORD dwProcessId); +static bool get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext, + unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare); + /* Returns 0 if path doesn't exist, >0 if path is a directory, * <0 if path is a file. */ @@ -84,8 +97,26 @@ fhandler_process::fhandler_process (): int fhandler_process::fstat (struct __stat64 *buf, path_conv *pc) { - int file_type = exists (get_name ()); + const char *path = get_name (); + int file_type = exists (path); (void) fhandler_base::fstat (buf, pc); + path += proc_len + 1; + int pid = atoi (path); + winpids pids; + _pinfo *p; + for (unsigned i = 0; i < pids.npids; i++) + { + p = pids[i]; + + if (!proc_exists (p)) + continue; + + if (p->pid == pid) + goto found; + } + set_errno(ENOENT); + return -1; +found: buf->st_mode &= ~_IFMT & NO_W; switch (file_type) @@ -97,12 +128,18 @@ fhandler_process::fstat (struct __stat64 *buf, path_conv *pc) buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; return 0; case 2: + buf->st_ctime = buf->st_mtime = p->start_time; + buf->st_atime = time(NULL); + buf->st_uid = p->uid; + buf->st_gid = p->gid; buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH; buf->st_nlink = PROCESS_LINK_COUNT; return 0; default: case -1: - buf->st_mode |= S_IFREG; + buf->st_uid = p->uid; + buf->st_gid = p->gid; + buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; return 0; } } @@ -198,7 +235,36 @@ fhandler_process::open (path_conv *pc, int flags, mode_t mode) res = 0; goto out; found: - switch (process_file_no) + fileid = process_file_no; + saved_pid = pid; + saved_p = p; + fill_filebuf (); + + if (flags & O_APPEND) + position = filesize; + else + position = 0; + +success: + res = 1; + set_open_status (); + set_flags (flags); +out: + syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + return res; +} + +void +fhandler_process::fill_filebuf () +{ + // has this process gone away? + if (!proc_exists (saved_p) || saved_p->pid != saved_pid) + { + if (filebuf) + cfree(filebuf); + filesize = 0; bufalloc = (size_t) -1; + } + switch (fileid) { case PROCESS_UID: case PROCESS_GID: @@ -207,25 +273,31 @@ found: case PROCESS_CTTY: case PROCESS_PPID: { + if (!filebuf) filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40); int num; - switch (process_file_no) + switch (fileid) { case PROCESS_PPID: - num = p->ppid; + num = saved_p->ppid; break; case PROCESS_UID: - num = p->uid; + num = saved_p->uid; break; case PROCESS_PGID: - num = p->pgid; + num = saved_p->pgid; break; case PROCESS_SID: - num = p->sid; + num = saved_p->sid; + break; + case PROCESS_GID: + num = saved_p->gid; break; - default: case PROCESS_CTTY: - num = p->ctty; + num = saved_p->ctty; + break; + default: // what's this here for? + num = 0; break; } __small_sprintf (filebuf, "%d\n", num); @@ -234,12 +306,13 @@ found: } case PROCESS_EXENAME: { + if (!filebuf) filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH); - if (p->process_state & (PID_ZOMBIE | PID_EXITED)) + if (saved_p->process_state & (PID_ZOMBIE | PID_EXITED)) strcpy (filebuf, "<defunct>"); else { - mount_table->conv_to_posix_path (p->progname, filebuf, 1); + mount_table->conv_to_posix_path (saved_p->progname, filebuf, 1); int len = strlen (filebuf); if (len > 4) { @@ -253,47 +326,428 @@ found: } case PROCESS_WINPID: { + if (!filebuf) filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40); - __small_sprintf (filebuf, "%d\n", p->dwProcessId); + __small_sprintf (filebuf, "%d\n", saved_p->dwProcessId); filesize = strlen (filebuf); break; } case PROCESS_WINEXENAME: { - int len = strlen (p->progname); + int len = strlen (saved_p->progname); + if (!filebuf) filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2)); - strcpy (filebuf, p->progname); + strcpy (filebuf, saved_p->progname); filebuf[len] = '\n'; filesize = len + 1; break; } case PROCESS_STATUS: { - filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 3); - filebuf[0] = ' '; - filebuf[1] = '\n'; - filebuf[2] = 0; - if (p->process_state & PID_STOPPED) - filebuf[0] = 'S'; - else if (p->process_state & PID_TTYIN) - filebuf[0] = 'I'; - else if (p->process_state & PID_TTYOU) - filebuf[0] = 'O'; - filesize = 2; + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048); + filesize = format_process_status (saved_p, filebuf, bufalloc); + break; + } + case PROCESS_STAT: + { + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048); + filesize = format_process_stat (saved_p, filebuf, bufalloc); break; } + case PROCESS_STATM: + { + if (!filebuf) + filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048); + filesize = format_process_statm (saved_p, filebuf, bufalloc); + break; + } } +} - if (flags & O_APPEND) - position = filesize; +static +off_t +format_process_stat (_pinfo *p, char *destbuf, size_t maxsize) +{ + char cmd[MAX_PATH]; + int state = 'R'; + unsigned long fault_count = 0UL, + utime = 0UL, stime = 0UL, + start_time = 0UL, + vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL; + int priority = 0; + if (p->process_state & (PID_ZOMBIE | PID_EXITED)) + strcpy (cmd, "<defunct"); else - position = 0; + { + strcpy(cmd, p->progname); + char *last_slash = strrchr (cmd, '\\'); + if (last_slash != NULL) + strcpy (cmd, last_slash + 1); + int len = strlen (cmd); + if (len > 4) + { + char *s = cmd + len - 4; + if (strcasecmp (s, ".exe") == 0) + *s = 0; + } + } + /* + * Note: under Windows, a _process_ is always running - it's only _threads_ + * that get suspended. Therefore the default state is R (runnable). + */ + if (p->process_state & PID_ZOMBIE) + state = 'Z'; + else if (p->process_state & PID_STOPPED) + state = 'T'; + else if (wincap.is_winnt ()) + state = get_process_state (p->dwProcessId); + if (wincap.is_winnt ()) + { + NTSTATUS ret; + HANDLE hProcess; + VM_COUNTERS vmc; + KERNEL_USER_TIMES put; + PROCESS_BASIC_INFORMATION pbi; + QUOTA_LIMITS ql; + SYSTEM_TIME_OF_DAY_INFORMATION stodi; + SYSTEM_PROCESSOR_TIMES spt; + hProcess = OpenProcess (PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, + FALSE, p->dwProcessId); + if (hProcess != NULL) + { + ret = ZwQueryInformationProcess (hProcess, + ProcessVmCounters, + (PVOID) &vmc, + sizeof vmc, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQueryInformationProcess (hProcess, + ProcessTimes, + (PVOID) &put, + sizeof put, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQueryInformationProcess (hProcess, + ProcessBasicInformation, + (PVOID) &pbi, + sizeof pbi, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQueryInformationProcess (hProcess, + ProcessQuotaLimits, + (PVOID) &ql, + sizeof ql, NULL); + CloseHandle (hProcess); + } + else + { + DWORD error = GetLastError (); + __seterrno_from_win_error (error); + debug_printf("OpenProcess: ret = %d", + error); + return 0; + } + if (ret == STATUS_SUCCESS) + ret = ZwQuerySystemInformation (SystemTimeOfDayInformation, + (PVOID) &stodi, + sizeof stodi, NULL); + if (ret == STATUS_SUCCESS) + ret = ZwQuerySystemInformation (SystemProcessorTimes, + (PVOID) &spt, + sizeof spt, NULL); + if (ret != STATUS_SUCCESS) + { + __seterrno_from_win_error (RtlNtStatusToDosError (ret)); + debug_printf("NtQueryInformationProcess: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + return 0; + } + fault_count = vmc.PageFaultCount; + utime = put.UserTime.QuadPart / 100000ULL; + stime = put.KernelTime.QuadPart / 100000ULL; + if (stodi.CurrentTime.QuadPart > put.CreateTime.QuadPart) + start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart + + spt.IdleTime.QuadPart + spt.UserTime.QuadPart + + spt.DpcTime.QuadPart - stodi.CurrentTime.QuadPart + + put.CreateTime.QuadPart) / 100000ULL; + else + /* + * sometimes stodi.CurrentTime is a bit behind + * Note: some older versions of procps are broken and can't cope + * with process start times > time(NULL). + */ + start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart + + spt.IdleTime.QuadPart + spt.UserTime.QuadPart + + spt.DpcTime.QuadPart) / 100000ULL; + priority = pbi.BasePriority; + unsigned page_size = getpagesize(); + vmsize = vmc.VirtualSize; + vmrss = vmc.WorkingSetSize / page_size; + vmmaxrss = ql.MaximumWorkingSetSize / page_size; + } + else + { + start_time = (GetTickCount() / 1000 - time(NULL) + p->start_time) * 100; + } + return __small_sprintf (destbuf, "%d (%s) %c " + "%d %d %d %d %d " + "%lu %lu %lu %lu %lu %lu %lu " + "%ld %ld %ld %ld %ld %ld " + "%lu %lu " + "%ld " + "%lu", + p->pid, cmd, + state, + p->ppid, p->pgid, p->sid, p->ctty, -1, + 0, fault_count, fault_count, 0, 0, utime, stime, + utime, stime, priority, 0, 0, 0, + start_time, vmsize, + vmrss, vmmaxrss + ); +} -success: - res = 1; - set_open_status (); - set_flags (flags); +static +off_t +format_process_status (_pinfo *p, char *destbuf, size_t maxsize) +{ + char cmd[MAX_PATH]; + int state = 'R'; + const char *state_str = "unknown"; + unsigned long vmsize = 0UL, vmrss = 0UL, vmdata = 0UL, vmlib = 0UL, vmtext = 0UL, + vmshare = 0UL; + if (p->process_state & (PID_ZOMBIE | PID_EXITED)) + strcpy (cmd, "<defunct>"); + else + { + strcpy(cmd, p->progname); + char *last_slash = strrchr (cmd, '\\'); + if (last_slash != NULL) + strcpy (cmd, last_slash + 1); + int len = strlen (cmd); + if (len > 4) + { + char *s = cmd + len - 4; + if (strcasecmp (s, ".exe") == 0) + *s = 0; + } + } + /* + * Note: under Windows, a _process_ is always running - it's only _threads_ + * that get suspended. Therefore the default state is R (runnable). + */ + if (p->process_state & PID_ZOMBIE) + state = 'Z'; + else if (p->process_state & PID_STOPPED) + state = 'T'; + else if (wincap.is_winnt ()) + state = get_process_state (p->dwProcessId); + switch (state) + { + case 'O': + state_str = "running"; + break; + case 'D': + case 'S': + state_str = "sleeping"; + break; + case 'R': + state_str = "runnable"; + break; + case 'Z': + state_str = "zombie"; + break; + case 'T': + state_str = "stopped"; + break; + } + if (wincap.is_winnt ()) + { + if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare)) + return 0; + unsigned page_size = getpagesize(); + vmsize *= page_size; vmrss *= page_size; vmdata *= page_size; + vmtext *= page_size; vmlib *= page_size; + } + return __small_sprintf (destbuf, "Name: %s\n" + "State: %c (%s)\n" + "Tgid: %d\n" + "Pid: %d\n" + "PPid: %d\n" + "Uid: %d %d %d %d\n" + "Gid: %d %d %d %d\n" + "VmSize: %8d kB\n" + "VmLck: %8d kB\n" + "VmRSS: %8d kB\n" + "VmData: %8d kB\n" + "VmStk: %8d kB\n" + "VmExe: %8d kB\n" + "VmLib: %8d kB\n" + "SigPnd: %016x\n" + "SigBlk: %016x\n" + "SigIgn: %016x\n", + cmd, + state, state_str, + p->pgid, + p->pid, + p->ppid, + p->uid, cygheap->user.real_uid, cygheap->user.real_uid, p->uid, + p->gid, cygheap->user.real_gid, cygheap->user.real_gid, p->gid, + vmsize >> 10, 0, vmrss >> 10, vmdata >> 10, 0, vmtext >> 10, vmlib >> 10, + 0, 0, p->getsigmask () + ); +} + +static +off_t +format_process_statm (_pinfo *p, char *destbuf, size_t maxsize) +{ + unsigned long vmsize = 0UL, vmrss = 0UL, vmtext = 0UL, vmdata = 0UL, vmlib = 0UL, + vmshare = 0UL; + if (wincap.is_winnt ()) + { + if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare)) + return 0; + } + return __small_sprintf (destbuf, "%ld %ld %ld %ld %ld %ld %ld", + vmsize, vmrss, vmshare, vmtext, vmlib, vmdata, 0 + ); +} + +static +int +get_process_state (DWORD dwProcessId) +{ + /* + * This isn't really heavy magic - just go through the processes' + * threads one by one and return a value accordingly + * Errors are silently ignored. + */ + NTSTATUS ret; + SYSTEM_PROCESSES *sp; + ULONG n = 0x1000; + PULONG p = new ULONG[n]; + int state =' '; + while (STATUS_INFO_LENGTH_MISMATCH == + (ret = ZwQuerySystemInformation (SystemProcessesAndThreadsInformation, + (PVOID) p, + n * sizeof *p, NULL))) + delete [] p, p = new ULONG[n *= 2]; + if (ret != STATUS_SUCCESS) + { + debug_printf("NtQuerySystemInformation: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + goto out; + } + state = 'Z'; + sp = (SYSTEM_PROCESSES *) p; + for (;;) + { + if (sp->ProcessId == dwProcessId) + { + SYSTEM_THREADS *st; + if (wincap.has_process_io_counters ()) + /* + * Windows 2000 and XP have an extra member in SYSTEM_PROCESSES + * which means the offset of the first SYSTEM_THREADS entry is + * different on these operating systems compared to NT 4. + */ + st = &sp->Threads[0]; + else + /* + * 136 is the offset of the first SYSTEM_THREADS entry on + * Windows NT 4. + */ + st = (SYSTEM_THREADS *) ((char *) sp + 136); + state = 'S'; + for (unsigned i = 0; i < sp->ThreadCount; i++) + { + if (st->State == StateRunning || + st->State == StateReady) + { + state = 'R'; + goto out; + } + st++; + } + break; + } + if (!sp->NextEntryDelta) + break; + sp = (SYSTEM_PROCESSES *) ((char *) sp + sp->NextEntryDelta); + } out: - syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode); + delete [] p; + return state; +} + +static +bool +get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext, + unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare) +{ + bool res = true; + NTSTATUS ret; + HANDLE hProcess; + VM_COUNTERS vmc; + MEMORY_WORKING_SET_LIST *mwsl; + ULONG n = 0x1000, length; + PULONG p = new ULONG[n]; + unsigned page_size = getpagesize(); + hProcess = OpenProcess (PROCESS_QUERY_INFORMATION, + FALSE, dwProcessId); + if (hProcess == NULL) + { + DWORD error = GetLastError(); + __seterrno_from_win_error (error); + debug_printf("OpenProcess: ret = %d", + error); + return false; + } + while ((ret = ZwQueryVirtualMemory (hProcess, 0, + MemoryWorkingSetList, + (PVOID) p, + n * sizeof *p, &length)), + (ret == STATUS_SUCCESS || ret == STATUS_INFO_LENGTH_MISMATCH) && + length >= n * sizeof *p) + delete [] p, p = new ULONG[n *= 2]; + if (ret != STATUS_SUCCESS) + { + debug_printf("NtQueryVirtualMemory: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + res = false; + goto out; + } + mwsl = (MEMORY_WORKING_SET_LIST *) p; + for (unsigned long i = 0; i < mwsl->NumberOfPages; i++) + { + ++*vmrss; + unsigned flags = mwsl->WorkingSetList[i] & 0x0FFF; + if (flags & (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE) == (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE)) + ++*vmlib; + else if (flags & WSLE_PAGE_SHAREABLE) + ++*vmshare; + else if (flags & WSLE_PAGE_EXECUTE) + ++*vmtext; + else + ++*vmdata; + } + ret = ZwQueryInformationProcess (hProcess, + ProcessVmCounters, + (PVOID) &vmc, + sizeof vmc, NULL); + if (ret != STATUS_SUCCESS) + { + debug_printf("NtQueryInformationProcess: ret = %d, " + "Dos(ret) = %d", + ret, RtlNtStatusToDosError (ret)); + res = false; + goto out; + } + *vmsize = vmc.VirtualSize / page_size; +out: + delete [] p; + CloseHandle (hProcess); return res; } diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc index e0938e7..4fc5024 100644 --- a/winsup/cygwin/fhandler_registry.cc +++ b/winsup/cygwin/fhandler_registry.cc @@ -292,7 +292,7 @@ fhandler_registry::telldir (DIR * dir) } void -fhandler_registry::seekdir (DIR * dir, __off32_t loc) +fhandler_registry::seekdir (DIR * dir, __off64_t loc) { /* Unfortunately cannot simply set __d_position due to transition from sub-keys to * values. @@ -490,6 +490,11 @@ out: return res; } +void +fhandler_registry::fill_filebuf () +{ +} + /* Auxillary member function to open registry keys. */ HKEY fhandler_registry::open_key (const char *name, REGSAM access, bool isValue) diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc index fa774f0..29b7ceb 100644 --- a/winsup/cygwin/fhandler_virtual.cc +++ b/winsup/cygwin/fhandler_virtual.cc @@ -27,7 +27,8 @@ details. */ #include <dirent.h> fhandler_virtual::fhandler_virtual (DWORD devtype): - fhandler_base (devtype), filebuf (NULL), bufalloc (-1) + fhandler_base (devtype), filebuf (NULL), bufalloc ((size_t) -1), + fileid (-1) { } @@ -89,7 +90,7 @@ __off64_t fhandler_virtual::telldir (DIR * dir) } void -fhandler_virtual::seekdir (DIR * dir, __off32_t loc) +fhandler_virtual::seekdir (DIR * dir, __off64_t loc) { dir->__d_position = loc; return; @@ -109,8 +110,13 @@ fhandler_virtual::closedir (DIR * dir) } __off64_t -fhandler_virtual::lseek (__off32_t offset, int whence) +fhandler_virtual::lseek (__off64_t offset, int whence) { + /* + * On Linux, when you lseek within a /proc file, + * the contents of the file are updated. + */ + fill_filebuf (); switch (whence) { case SEEK_SET: @@ -124,7 +130,7 @@ fhandler_virtual::lseek (__off32_t offset, int whence) break; default: set_errno (EINVAL); - return (__off32_t) -1; + return (__off64_t) -1; } return position; } @@ -214,3 +220,8 @@ fhandler_virtual::exists (const char *path) { return 0; } + +void +fhandler_virtual::fill_filebuf () +{ +} diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index e1ec33b..f2a96aa 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -10,11 +10,28 @@ #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004) #define FILE_SYNCHRONOUS_IO_NONALERT 32 +#define PDI_MODULES 0x01 +#define PDI_HEAPS 0x04 +#define LDRP_IMAGE_DLL 0x00000004 +#define WSLE_PAGE_READONLY 0x001 +#define WSLE_PAGE_EXECUTE 0x002 +#define WSLE_PAGE_EXECUTE_READ 0x003 +#define WSLE_PAGE_READWRITE 0x004 +#define WSLE_PAGE_WRITECOPY 0x005 +#define WSLE_PAGE_EXECUTE_READWRITE 0x006 +#define WSLE_PAGE_EXECUTE_WRITECOPY 0x007 +#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0 +#define WSLE_PAGE_SHAREABLE 0x100 + +typedef ULONG KAFFINITY; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, + SystemPerformanceInformation = 2, + SystemTimeOfDayInformation = 3, SystemProcessesAndThreadsInformation = 5, + SystemProcessorTimes = 8, /* There are a lot more of these... */ } SYSTEM_INFORMATION_CLASS; @@ -30,9 +47,19 @@ typedef struct _SYSTEM_BASIC_INFORMATION ULONG LowestUserAddress; ULONG HighestUserAddress; ULONG ActiveProcessors; - ULONG NumberProcessors; + UCHAR NumberProcessors; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; +typedef struct _SYSTEM_PROCESSOR_TIMES +{ + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; +} SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES; + typedef LONG KPRIORITY; typedef struct _VM_COUNTERS { @@ -112,12 +139,13 @@ typedef struct _SYSTEM_THREADS ULONG ContextSwitchCount; THREAD_STATE State; KWAIT_REASON WaitReason; + DWORD Reserved; } SYSTEM_THREADS, *PSYSTEM_THREADS; typedef struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; - ULONG Threadcount; + ULONG ThreadCount; ULONG Reserved1[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; @@ -139,6 +167,180 @@ typedef struct _IO_STATUS_BLOCK ULONG Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; +typedef struct _SYSTEM_PERFORMANCE_INFORMATION +{ + LARGE_INTEGER IdleTime; + LARGE_INTEGER ReadTransferCount; + LARGE_INTEGER WriteTransferCount; + LARGE_INTEGER OtherTransferCount; + ULONG ReadOperationCount; + ULONG WriteOperationCount; + ULONG OtherOperationCount; + ULONG AvailablePages; + ULONG TotalCommittedPages; + ULONG TotalCommitLimit; + ULONG PeakCommitment; + ULONG PageFaults; + ULONG WriteCopyFaults; + ULONG TransitionFaults; + ULONG Reserved1; + ULONG DemandZeroFaults; + ULONG PagesRead; + ULONG PageReadIos; + ULONG Reserved2[2]; + ULONG PagefilePagesWritten; + ULONG PagefilePageWriteIos; + ULONG MappedFilePagesWritten; + ULONG MappedFilePageWriteIos; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG TotalFreeSystemPtes; + ULONG SystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG SmallNonPagedLookasideListAllocateHits; + ULONG SmallPagedLookasideListAllocateHits; + ULONG Reserved3; + ULONG MmSystemCachePage; + ULONG PagedPoolPage; + ULONG SystemDriverPage; + ULONG FastReadNoWait; + ULONG FastReadWait; + ULONG FastReadResourceMiss; + ULONG FastReadNotPossible; + ULONG FastMdlReadNoWait; + ULONG FastMdlReadWait; + ULONG FastMdlReadResourceMiss; + ULONG FastMdlReadNotPossible; + ULONG MapDataNoWait; + ULONG MapDataWait; + ULONG MapDataNoWaitMiss; + ULONG MapDataWaitMiss; + ULONG PinMappedDataCount; + ULONG PinReadNoWait; + ULONG PinReadWait; + ULONG PinReadNoWaitMiss; + ULONG PinReadWaitMiss; + ULONG CopyReadNoWait; + ULONG CopyReadWait; + ULONG CopyReadNoWaitMiss; + ULONG CopyReadWaitMiss; + ULONG MdlReadNoWait; + ULONG MdlReadWait; + ULONG MdlReadNoWaitMiss; + ULONG MdlReadWaitMiss; + ULONG ReadAheadIos; + ULONG LazyWriteIos; + ULONG LazyWritePages; + ULONG DataFlushes; + ULONG DataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; +} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; + +typedef struct _SYSTEM_TIME_OF_DAY_INFORMATION +{ + LARGE_INTEGER BootTime; + LARGE_INTEGER CurrentTime; + LARGE_INTEGER TimeZoneBias; + ULONG CurrentTimeZoneId; +} SYSTEM_TIME_OF_DAY_INFORMATION, *PSYSTEM_TIME_OF_DAY_INFORMATION; + +typedef enum _PROCESSINFOCLASS +{ + ProcessBasicInformation = 0, + ProcessQuotaLimits = 1, + ProcessVmCounters = 3, + ProcessTimes =4, +} PROCESSINFOCLASS; + +typedef struct _DEBUG_BUFFER +{ + HANDLE SectionHandle; + PVOID SectionBase; + PVOID RemoteSectionBase; + ULONG SectionBaseDelta; + HANDLE EventPairHandle; + ULONG Unknown[2]; + HANDLE RemoteThreadHandle; + ULONG InfoClassMask; + ULONG SizeOfInfo; + ULONG AllocatedSize; + ULONG SectionSize; + PVOID ModuleInformation; + PVOID BackTraceInformation; + PVOID HeapInformation; + PVOID LockInformation; + PVOID Reserved[9]; +} DEBUG_BUFFER, *PDEBUG_BUFFER; + +typedef struct _DEBUG_HEAP_INFORMATION +{ + ULONG Base; + ULONG Flags; + USHORT Granularity; + USHORT Unknown; + ULONG Allocated; + ULONG Committed; + ULONG TagCount; + ULONG BlockCount; + ULONG Reserved[7]; + PVOID Tags; + PVOID Blocks; +} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION; + +typedef struct _DEBUG_MODULE_INFORMATION +{ + ULONG Reserved[2]; + ULONG Base; + ULONG Size; + ULONG Flags; + USHORT Index; + USHORT Unknown; + USHORT LoadCount; + USHORT ModuleNameOffset; + CHAR ImageName[256]; +} DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION; + +typedef struct _KERNEL_USER_TIMES +{ + LARGE_INTEGER CreateTime; + LARGE_INTEGER ExitTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; +} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; + +typedef void *PPEB; + +typedef struct _PROCESS_BASIC_INFORMATION +{ + NTSTATUS ExitStatus; + PPEB PebBaseAddress; + KAFFINITY AffinityMask; + KPRIORITY BasePriority; + ULONG UniqueProcessId; + ULONG InheritedFromUniqueProcessId; +} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; + +typedef enum _MEMORY_INFORMATION_CLASS +{ + MemoryBasicInformation, + MemoryWorkingSetList, + MemorySectionName, + MemoryBaiscVlmInformation +} MEMORY_INFORMATION_CLASS; + +typedef struct _MEMORY_WORKING_SET_LIST { + ULONG NumberOfPages; + ULONG WorkingSetList[1]; +} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST; + /* Function declarations for ntdll.dll. These don't appear in any standard Win32 header. */ extern "C" @@ -162,4 +364,8 @@ extern "C" NTSTATUS NTAPI ZwQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS, IN OUT PVOID, IN ULONG, OUT PULONG); + NTSTATUS NTAPI ZwQueryInformationProcess (IN HANDLE, IN PROCESSINFOCLASS, + OUT PVOID, IN ULONG, OUT PULONG); + NTSTATUS NTAPI ZwQueryVirtualMemory (IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS, + OUT PVOID, IN ULONG, OUT PULONG); } diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc index 09e95fb..1b3fd4b 100644 --- a/winsup/cygwin/wincap.cc +++ b/winsup/cygwin/wincap.cc @@ -46,6 +46,7 @@ static NO_COPY wincaps wincap_unknown = { has_raw_devices:false, has_valid_processorlevel:false, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_95 = { @@ -83,6 +84,7 @@ static NO_COPY wincaps wincap_95 = { has_raw_devices:false, has_valid_processorlevel:false, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_95osr2 = { @@ -120,6 +122,7 @@ static NO_COPY wincaps wincap_95osr2 = { has_raw_devices:false, has_valid_processorlevel:false, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_98 = { @@ -157,6 +160,7 @@ static NO_COPY wincaps wincap_98 = { has_raw_devices:false, has_valid_processorlevel:true, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_98se = { @@ -194,6 +198,7 @@ static NO_COPY wincaps wincap_98se = { has_raw_devices:false, has_valid_processorlevel:true, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_me = { @@ -231,6 +236,7 @@ static NO_COPY wincaps wincap_me = { has_raw_devices:false, has_valid_processorlevel:true, has_64bit_file_access:false, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_nt3 = { @@ -268,6 +274,7 @@ static NO_COPY wincaps wincap_nt3 = { has_raw_devices:true, has_valid_processorlevel:true, has_64bit_file_access:true, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_nt4 = { @@ -305,6 +312,7 @@ static NO_COPY wincaps wincap_nt4 = { has_raw_devices:true, has_valid_processorlevel:true, has_64bit_file_access:true, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_nt4sp4 = { @@ -342,6 +350,7 @@ static NO_COPY wincaps wincap_nt4sp4 = { has_raw_devices:true, has_valid_processorlevel:true, has_64bit_file_access:true, + has_process_io_counters:false, }; static NO_COPY wincaps wincap_2000 = { @@ -379,6 +388,7 @@ static NO_COPY wincaps wincap_2000 = { has_raw_devices:true, has_valid_processorlevel:true, has_64bit_file_access:true, + has_process_io_counters:true, }; static NO_COPY wincaps wincap_xp = { @@ -416,6 +426,7 @@ static NO_COPY wincaps wincap_xp = { has_raw_devices:true, has_valid_processorlevel:true, has_64bit_file_access:true, + has_process_io_counters:true, }; wincapc NO_COPY wincap; diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h index 088907a..c33c3cf 100644 --- a/winsup/cygwin/wincap.h +++ b/winsup/cygwin/wincap.h @@ -47,6 +47,7 @@ struct wincaps unsigned has_raw_devices : 1; unsigned has_valid_processorlevel : 1; unsigned has_64bit_file_access : 1; + unsigned has_process_io_counters : 1; }; class wincapc @@ -99,6 +100,7 @@ public: bool IMPLEMENT (has_raw_devices) bool IMPLEMENT (has_valid_processorlevel) bool IMPLEMENT (has_64bit_file_access) + bool IMPLEMENT (has_process_io_counters) #undef IMPLEMENT }; |