Also implement GetProcessWorkingSetSize on top this.
-- v4: kernelbase: Implement GetProcessWorkingSetSizeEx(). ntdll: Implement QUOTA_LIMITS_EX for NtQueryProcessInformation(ProcessQuotaLimits).
From: Vijay Kiran Kamuju infyquest@gmail.com
--- dlls/ntdll/tests/info.c | 41 +++++++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/process.c | 13 ++++++++++--- dlls/wow64/process.c | 34 ++++++++++++++++++++++---------- dlls/wow64/struct32.h | 25 ++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 7741293d815..3fa73bf40e9 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2687,6 +2687,7 @@ static void test_query_process_debug_flags(int argc, char **argv) static void test_query_process_quota_limits(void) { QUOTA_LIMITS qlimits; + QUOTA_LIMITS_EX qlimitsex; NTSTATUS status; HANDLE process; ULONG ret_len; @@ -2694,9 +2695,15 @@ static void test_query_process_quota_limits(void) status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, NULL, sizeof(qlimits), NULL); ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status);
+ status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, NULL, sizeof(qlimitsex), NULL); + ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status); + status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, &qlimits, sizeof(qlimits), NULL); ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status);
+ status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, &qlimitsex, sizeof(qlimitsex), NULL); + ok(status == STATUS_INVALID_HANDLE, "NtQueryInformationProcess failed, status %#lx.\n", status); + process = GetCurrentProcess(); status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, 2, &ret_len); ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); @@ -2735,6 +2742,40 @@ static void test_query_process_quota_limits(void) status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits) + 1, &ret_len); ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len); + + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimitsex, 2, &ret_len); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); + + memset(&qlimitsex, 0, sizeof(qlimitsex)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimitsex, sizeof(qlimitsex), &ret_len); + ok(status == STATUS_SUCCESS, "NtQueryInformationProcess failed, status %#lx.\n", status); + ok(sizeof(qlimitsex) == ret_len, "len set to %lx\n", ret_len); + ok(qlimitsex.WorkingSetLimit == ~0,"Expected WorkingLimit = ~0, got %s\n", + wine_dbgstr_longlong(qlimitsex.WorkingSetLimit)); + ok(qlimitsex.Flags == 0xa,"Expected Flags = 0xa, got %#lx\n", qlimitsex.Flags); + ok(qlimitsex.CpuRateLimit.RateData == 0 || broken(qlimitsex.CpuRateLimit.RateData == 100) /* Win7*/, + "Expected RateData = 0, got %lu\n", qlimitsex.CpuRateLimit.RateData); + + if (winetest_debug > 1) + { + trace("WorkingSetLimit: %s\n", wine_dbgstr_longlong(qlimitsex.WorkingSetLimit)); + trace("CpuRateLimit: %lu\n", qlimitsex.CpuRateLimit.RateData); + } + + memset(&qlimitsex, 0, sizeof(qlimitsex)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimitsex, sizeof(qlimitsex) * 2, &ret_len); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); + ok(sizeof(qlimitsex) == ret_len, "len set to %lx\n", ret_len); + + memset(&qlimitsex, 0, sizeof(qlimitsex)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimitsex, sizeof(qlimitsex) - 1, &ret_len); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); + ok(sizeof(qlimitsex) == ret_len, "len set to %lx\n", ret_len); + + memset(&qlimitsex, 0, sizeof(qlimitsex)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimitsex, sizeof(qlimitsex) + 1, &ret_len); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); + ok(sizeof(qlimitsex) == ret_len, "len set to %lx\n", ret_len); }
static void test_readvirtualmemory(void) diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index ec585fe2d6c..3924bbb92e6 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -1579,16 +1579,16 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class
case ProcessQuotaLimits: { - QUOTA_LIMITS qlimits; + QUOTA_LIMITS_EX qlimits;
FIXME( "ProcessQuotaLimits (%p,%p,0x%08x,%p) stub\n", handle, info, (int)size, ret_len );
- len = sizeof(QUOTA_LIMITS); - if (size == len) + if (size == sizeof(QUOTA_LIMITS) || size == sizeof(QUOTA_LIMITS_EX)) { if (!handle) ret = STATUS_INVALID_HANDLE; else { + memset(&qlimits, 0, sizeof(qlimits)); /* FIXME: SetProcessWorkingSetSize can also set the quota values. Quota Limits should be stored inside the process. */ qlimits.PagedPoolLimit = (SIZE_T)-1; @@ -1599,6 +1599,13 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class qlimits.MaximumWorkingSetSize = 1413120; qlimits.PagefileLimit = (SIZE_T)-1; qlimits.TimeLimit.QuadPart = -1; + if (size == sizeof(QUOTA_LIMITS_EX)) + { + qlimits.WorkingSetLimit = (SIZE_T)-1; + qlimits.Flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE|QUOTA_LIMITS_HARDWS_MAX_DISABLE; + } + len = size; + if (len != sizeof(QUOTA_LIMITS)) len = sizeof(QUOTA_LIMITS_EX); memcpy(info, &qlimits, len); } } diff --git a/dlls/wow64/process.c b/dlls/wow64/process.c index 6375f63c70b..a3d83b8b19f 100644 --- a/dlls/wow64/process.c +++ b/dlls/wow64/process.c @@ -252,6 +252,25 @@ static void put_ps_attributes( PS_ATTRIBUTE_LIST32 *attr32, const PS_ATTRIBUTE_L } }
+void put_quota_limits( QUOTA_LIMITS_EX32 *info32, const QUOTA_LIMITS_EX *info, ULONG size ) +{ + info32->PagedPoolLimit = info->PagedPoolLimit; + info32->NonPagedPoolLimit = info->NonPagedPoolLimit; + info32->MinimumWorkingSetSize = info->MinimumWorkingSetSize; + info32->MaximumWorkingSetSize = info->MaximumWorkingSetSize; + info32->PagefileLimit = info->PagefileLimit; + info32->TimeLimit = info->TimeLimit; + if (size == sizeof(QUOTA_LIMITS_EX32)) + { + info32->WorkingSetLimit = info->WorkingSetLimit; + info32->Reserved2 = info->Reserved2; + info32->Reserved3 = info->Reserved3; + info32->Reserved4 = info->Reserved4; + info32->Flags = info->Flags; + info32->CpuRateLimit.RateData = info->CpuRateLimit.RateData; + } +} + void put_vm_counters( VM_COUNTERS_EX32 *info32, const VM_COUNTERS_EX *info, ULONG size ) { info32->PeakVirtualSize = info->PeakVirtualSize; @@ -566,24 +585,19 @@ NTSTATUS WINAPI wow64_NtQueryInformationProcess( UINT *args ) return NtQueryInformationProcess( handle, class, ptr, len, retlen );
case ProcessQuotaLimits: /* QUOTA_LIMITS */ - if (len == sizeof(QUOTA_LIMITS32)) + if (len == sizeof(QUOTA_LIMITS32) || len == sizeof(QUOTA_LIMITS_EX32)) { - QUOTA_LIMITS info; - QUOTA_LIMITS32 *info32 = ptr; + QUOTA_LIMITS_EX info; + QUOTA_LIMITS_EX32 *info32 = ptr;
if (!(status = NtQueryInformationProcess( handle, class, &info, sizeof(info), NULL ))) { - info32->PagedPoolLimit = info.PagedPoolLimit; - info32->NonPagedPoolLimit = info.NonPagedPoolLimit; - info32->MinimumWorkingSetSize = info.MinimumWorkingSetSize; - info32->MaximumWorkingSetSize = info.MaximumWorkingSetSize; - info32->PagefileLimit = info.PagefileLimit; - info32->TimeLimit = info.TimeLimit; + put_quota_limits( info32, &info, len ); if (retlen) *retlen = len; } return status; } - if (retlen) *retlen = sizeof(QUOTA_LIMITS32); + if (retlen) *retlen = sizeof(QUOTA_LIMITS_EX32); return STATUS_INFO_LENGTH_MISMATCH;
case ProcessVmCounters: /* VM_COUNTERS_EX */ diff --git a/dlls/wow64/struct32.h b/dlls/wow64/struct32.h index fe2bbc758ee..6f88aa21c45 100644 --- a/dlls/wow64/struct32.h +++ b/dlls/wow64/struct32.h @@ -742,4 +742,29 @@ typedef struct LARGE_INTEGER TimeLimit; } QUOTA_LIMITS32;
+typedef union +{ + ULONG RateData; + struct + { + ULONG RatePercent:7; + ULONG Reserved0:25; + }; +} RATE_QUOTA_LIMIT32; + +typedef struct +{ + ULONG PagedPoolLimit; + ULONG NonPagedPoolLimit; + ULONG MinimumWorkingSetSize; + ULONG MaximumWorkingSetSize; + ULONG PagefileLimit; + LARGE_INTEGER TimeLimit; + ULONG WorkingSetLimit; + ULONG Reserved2; + ULONG Reserved3; + ULONG Reserved4; + ULONG Flags; + RATE_QUOTA_LIMIT32 CpuRateLimit; +} QUOTA_LIMITS_EX32; #endif /* __WOW64_STRUCT32_H */
From: Vijay Kiran Kamuju infyquest@gmail.com
--- dlls/kernelbase/process.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/dlls/kernelbase/process.c b/dlls/kernelbase/process.c index 2d08481cd35..f38d28489ad 100644 --- a/dlls/kernelbase/process.c +++ b/dlls/kernelbase/process.c @@ -27,6 +27,7 @@ #include "winbase.h" #include "winnls.h" #include "wincontypes.h" +#include "winnt.h" #include "winternl.h"
#include "kernelbase.h" @@ -966,12 +967,16 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetProcessVersion( DWORD pid ) BOOL WINAPI DECLSPEC_HOTPATCH GetProcessWorkingSetSizeEx( HANDLE process, SIZE_T *minset, SIZE_T *maxset, DWORD *flags) { - FIXME( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags ); - /* 32 MB working set size */ - if (minset) *minset = 32*1024*1024; - if (maxset) *maxset = 32*1024*1024; - if (flags) *flags = QUOTA_LIMITS_HARDWS_MIN_DISABLE | QUOTA_LIMITS_HARDWS_MAX_DISABLE; - return TRUE; + QUOTA_LIMITS_EX qlimits; + NTSTATUS status; + + TRACE( "(%p,%p,%p,%p): stub\n", process, minset, maxset, flags ); + + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits), NULL ); + if(minset) *minset = qlimits.MinimumWorkingSetSize; + if(maxset) *maxset = qlimits.MaximumWorkingSetSize; + if(flags) *flags = qlimits.Flags; + return set_ntstatus( status ); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=149337
Your paranoid android.
=== debian11 (32 bit report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit ar:MA report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit de report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit fr report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit he:IL report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit hi:IN report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit ja:JP report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11 (32 bit zh:CN report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11b (32 bit WoW report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
=== debian11b (64 bit WoW report) ===
ntdll: info.c:2734: Test failed: len set to 0 info.c:2739: Test failed: len set to 0 info.c:2744: Test failed: len set to 0 info.c:2768: Test failed: len set to 0 info.c:2773: Test failed: len set to 0 info.c:2778: Test failed: len set to 0
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 0000000002C000F0, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032