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 */