[PATCH v2 0/2] MR5269: Add NtQueryInformationProcess(ProcessQuotaLimits) stub
Based on a patch by Qian Hong. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=44812 -- v2: ntdll: Add NtQueryInformationProcess(ProcessQuotaLimits) tests. ntdll: Add NtQueryInformationProcess(ProcessQuotaLimits) stub. https://gitlab.winehq.org/wine/wine/-/merge_requests/5269
From: Vijay Kiran Kamuju <infyquest(a)gmail.com> Based on a patch by Qian Hong. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=44812 Signed-off-by: Gijs Vermeulen <gijsvrm(a)gmail.com> --- dlls/ntdll/unix/process.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c index 2c6dc1b43cc..b4ff3ea7fef 100644 --- a/dlls/ntdll/unix/process.c +++ b/dlls/ntdll/unix/process.c @@ -1124,7 +1124,6 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class switch (class) { - UNIMPLEMENTED_INFO_CLASS(ProcessQuotaLimits); UNIMPLEMENTED_INFO_CLASS(ProcessBasePriority); UNIMPLEMENTED_INFO_CLASS(ProcessRaisePriority); UNIMPLEMENTED_INFO_CLASS(ProcessExceptionPort); @@ -1580,6 +1579,36 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class else ret = STATUS_INVALID_PARAMETER; break; + case ProcessQuotaLimits: + { + QUOTA_LIMITS qlimits; + + FIXME( "ProcessQuotaLimits (%p,%p,0x%08x,%p) stub\n", handle, info, (int)size, ret_len ); + + len = sizeof(QUOTA_LIMITS); + if (size == len) + { + if (!info) ret = STATUS_ACCESS_VIOLATION; + else if (!handle) ret = STATUS_INVALID_HANDLE; + else + { + /* FIXME: SetProcessWorkingSetSize can also set the quota values. + Quota Limits should be stored inside the process. */ + qlimits.PagedPoolLimit = (SIZE_T)-1; + qlimits.NonPagedPoolLimit = (SIZE_T)-1; + /* Default minimum working set size is 204800 bytes (50 Pages) */ + qlimits.MinimumWorkingSetSize = 204800; + /* Default maximum working set size is 1413120 bytes (345 Pages) */ + qlimits.MaximumWorkingSetSize = 1413120; + qlimits.PagefileLimit = (SIZE_T)-1; + qlimits.TimeLimit.QuadPart = -1; + memcpy(info, &qlimits, len); + } + } + else ret = STATUS_INFO_LENGTH_MISMATCH; + break; + } + default: FIXME("(%p,info_class=%d,%p,0x%08x,%p) Unknown information class\n", handle, class, info, (int)size, ret_len ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5269
From: Vijay Kiran Kamuju <infyquest(a)gmail.com> Signed-off-by: Gijs Vermeulen <gijsvrm(a)gmail.com> --- dlls/ntdll/tests/info.c | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 6771bbe4e3f..26e01f0e252 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -2677,6 +2677,60 @@ static void test_query_process_debug_flags(int argc, char **argv) } } +static void test_query_process_quota_limits(void) +{ + QUOTA_LIMITS qlimits; + NTSTATUS status; + HANDLE process; + ULONG ret_len; + + status = NtQueryInformationProcess(NULL, ProcessQuotaLimits, NULL, sizeof(qlimits), NULL); + ok(status == STATUS_ACCESS_VIOLATION || 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); + + process = GetCurrentProcess(); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, 2, &ret_len); + ok(status == STATUS_INFO_LENGTH_MISMATCH, "NtQueryInformationProcess failed, status %#lx.\n", status); + + memset(&qlimits, 0, sizeof(qlimits)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits), &ret_len); + ok(status == STATUS_SUCCESS, "NtQueryInformationProcess failed, status %#lx.\n", status); + ok(sizeof(qlimits) == ret_len, "len set to %lx\n", ret_len); + ok(qlimits.MinimumWorkingSetSize == 204800,"Expected MinimumWorkingSetSize = 204800, got %s\n", + wine_dbgstr_longlong(qlimits.MinimumWorkingSetSize)); + ok(qlimits.MaximumWorkingSetSize == 1413120,"Expected MaximumWorkingSetSize = 1413120, got %s\n", + wine_dbgstr_longlong(qlimits.MaximumWorkingSetSize)); + ok(qlimits.PagefileLimit == ~0,"Expected PagefileLimit = ~0, got %s\n", + wine_dbgstr_longlong(qlimits.PagefileLimit)); + ok(qlimits.TimeLimit.QuadPart == ~0,"Expected TimeLimit = ~0, got %s\n", + wine_dbgstr_longlong(qlimits.TimeLimit.QuadPart)); + + if (winetest_debug > 1) + { + trace("Quota Limits:\n"); + trace("PagedPoolLimit: %s\n", wine_dbgstr_longlong(qlimits.PagedPoolLimit)); + trace("NonPagedPoolLimit: %s\n", wine_dbgstr_longlong(qlimits.NonPagedPoolLimit)); + } + + memset(&qlimits, 0, sizeof(qlimits)); + status = NtQueryInformationProcess( process, ProcessQuotaLimits, &qlimits, sizeof(qlimits) * 2, &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); + + memset(&qlimits, 0, sizeof(qlimits)); + 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); + + memset(&qlimits, 0, sizeof(qlimits)); + 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); +} + static void test_readvirtualmemory(void) { HANDLE process; @@ -3886,6 +3940,7 @@ START_TEST(info) test_query_process_debug_object_handle(argc, argv); test_query_process_debug_flags(argc, argv); test_query_process_image_info(); + test_query_process_quota_limits(); test_mapprotection(); test_threadstack(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/5269
On Tue Mar 19 12:39:20 2024 +0000, Gijs Vermeulen wrote:
Everything after WinXP seems to return `STATUS_INVALID_HANDLE`. Wine, however, still returns STATUS_ACCESS_VIOLATION consistently in this case for other classes. It's also done like this in other tests in this file, so maybe we should leave it as-is? We no longer test on WinXP reguarly. It doesn't make sense to allow behavior not exhibited by any actively tested Windows version. I'd suggest we leave this as todo\_wine.
```suggestion:-0+0 todo_wine ok(status == STATUS_INVALID_HANDLE, ``` Other classes would need similar treatment (but not in this MR). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/5269#note_65329
On Tue Mar 19 13:03:32 2024 +0000, Jinoh Kang wrote:
We no longer test on WinXP reguarly. It doesn't make sense to allow behavior not exhibited by any actively tested Windows version. I'd suggest we leave this as todo\_wine. ```suggestion:-0+0 todo_wine ok(status == STATUS_INVALID_HANDLE, ``` Other classes would need similar treatment (but not in this MR). If we're "breaking consistency" anyway, wouldn't it make more sense to just return the correct value for this class?
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5269#note_65330
On Tue Mar 19 13:12:32 2024 +0000, Gijs Vermeulen wrote:
If we're "breaking consistency" anyway, wouldn't it make more sense to just return the correct value for this class? My impression is that `STATUS_ACCESS_VIOLATION` is not necessarily something you'll return after explicit check, it might come from syscall exception handling. That means that after winxp there is an invalid handle check that wasn't there before.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/5269#note_65332
participants (4)
-
Gijs Vermeulen (@gverm) -
Jinoh Kang (@iamahuman) -
Nikolay Sivov (@nsivov) -
Vijay Kiran Kamuju