1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS API tests 3c2c66affSColin Finck * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4c2c66affSColin Finck * PURPOSE: Tests for the NtQueryInformationProcess API 5c2c66affSColin Finck * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6c2c66affSColin Finck */ 7c2c66affSColin Finck 8283bbe73SAmine Khaldi #include "precomp.h" 9c2c66affSColin Finck 10c2c66affSColin Finck static LARGE_INTEGER TestStartTime; 11c2c66affSColin Finck 12c2c66affSColin Finck static 13c2c66affSColin Finck void 14c2c66affSColin Finck Test_ProcessTimes(void) 15c2c66affSColin Finck { 16c2c66affSColin Finck #define SPIN_TIME 1000000 17c2c66affSColin Finck NTSTATUS Status; 18c2c66affSColin Finck KERNEL_USER_TIMES Times1; 19c2c66affSColin Finck KERNEL_USER_TIMES Times2; 20c2c66affSColin Finck ULONG Length; 21c2c66affSColin Finck LARGE_INTEGER Time1, Time2; 22c2c66affSColin Finck 23c2c66affSColin Finck /* Everything is NULL */ 24c2c66affSColin Finck Status = NtQueryInformationProcess(NULL, 25c2c66affSColin Finck ProcessTimes, 26c2c66affSColin Finck NULL, 27c2c66affSColin Finck 0, 28c2c66affSColin Finck NULL); 29c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 30c2c66affSColin Finck 31c2c66affSColin Finck /* Right size, invalid process */ 32c2c66affSColin Finck Status = NtQueryInformationProcess(NULL, 33c2c66affSColin Finck ProcessTimes, 34c2c66affSColin Finck NULL, 35c2c66affSColin Finck sizeof(KERNEL_USER_TIMES), 36c2c66affSColin Finck NULL); 37c2c66affSColin Finck ok_hex(Status, STATUS_INVALID_HANDLE); 38c2c66affSColin Finck 39c2c66affSColin Finck /* Valid process, no buffer */ 40c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 41c2c66affSColin Finck ProcessTimes, 42c2c66affSColin Finck NULL, 43c2c66affSColin Finck 0, 44c2c66affSColin Finck NULL); 45c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 46c2c66affSColin Finck 47c2c66affSColin Finck /* Unaligned buffer, wrong size */ 48c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 49c2c66affSColin Finck ProcessTimes, 50c2c66affSColin Finck (PVOID)2, 51c2c66affSColin Finck 0, 52c2c66affSColin Finck NULL); 53c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 54c2c66affSColin Finck 55c2c66affSColin Finck /* Unaligned buffer, correct size */ 56c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 57c2c66affSColin Finck ProcessTimes, 58c2c66affSColin Finck (PVOID)2, 59c2c66affSColin Finck sizeof(KERNEL_USER_TIMES), 60c2c66affSColin Finck NULL); 61c2c66affSColin Finck ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 62c2c66affSColin Finck 63c2c66affSColin Finck /* Buffer too small */ 64c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 65c2c66affSColin Finck ProcessTimes, 66c2c66affSColin Finck NULL, 67c2c66affSColin Finck sizeof(KERNEL_USER_TIMES) - 1, 68c2c66affSColin Finck NULL); 69c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 70c2c66affSColin Finck 71c2c66affSColin Finck /* Right buffer size but NULL pointer */ 72c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 73c2c66affSColin Finck ProcessTimes, 74c2c66affSColin Finck NULL, 75c2c66affSColin Finck sizeof(KERNEL_USER_TIMES), 76c2c66affSColin Finck NULL); 77c2c66affSColin Finck ok_hex(Status, STATUS_ACCESS_VIOLATION); 78c2c66affSColin Finck 79c2c66affSColin Finck /* Buffer too large */ 80c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 81c2c66affSColin Finck ProcessTimes, 82c2c66affSColin Finck NULL, 83c2c66affSColin Finck sizeof(KERNEL_USER_TIMES) + 1, 84c2c66affSColin Finck NULL); 85c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 86c2c66affSColin Finck 87c2c66affSColin Finck /* Buffer too small, ask for length */ 88c2c66affSColin Finck Length = 0x55555555; 89c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 90c2c66affSColin Finck ProcessTimes, 91c2c66affSColin Finck NULL, 92c2c66affSColin Finck sizeof(KERNEL_USER_TIMES) - 1, 93c2c66affSColin Finck &Length); 94c2c66affSColin Finck ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 95c2c66affSColin Finck ok_dec(Length, 0x55555555); 96c2c66affSColin Finck 97c2c66affSColin Finck Status = NtQuerySystemTime(&Time1); 98c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 99c2c66affSColin Finck 100c2c66affSColin Finck /* Do some busy waiting to increase UserTime */ 101c2c66affSColin Finck do 102c2c66affSColin Finck { 103c2c66affSColin Finck Status = NtQuerySystemTime(&Time2); 104c2c66affSColin Finck if (!NT_SUCCESS(Status)) 105c2c66affSColin Finck { 106c2c66affSColin Finck ok(0, "NtQuerySystemTime failed with %lx\n", Status); 107c2c66affSColin Finck break; 108c2c66affSColin Finck } 109c2c66affSColin Finck } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME); 110c2c66affSColin Finck 111c2c66affSColin Finck /* Valid parameters, no return length */ 112c2c66affSColin Finck Status = NtQuerySystemTime(&Time1); 113c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 114c2c66affSColin Finck 115c2c66affSColin Finck RtlFillMemory(&Times1, sizeof(Times1), 0x55); 116c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 117c2c66affSColin Finck ProcessTimes, 118c2c66affSColin Finck &Times1, 119c2c66affSColin Finck sizeof(KERNEL_USER_TIMES), 120c2c66affSColin Finck NULL); 121c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 122e26c8bc6STimo Kreuzer ros_skip_flaky 123c2c66affSColin Finck ok(Times1.CreateTime.QuadPart < TestStartTime.QuadPart, 124c2c66affSColin Finck "CreateTime is %I64u, expected < %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart); 125c2c66affSColin Finck ok(Times1.CreateTime.QuadPart > TestStartTime.QuadPart - 100000000LL, 126c2c66affSColin Finck "CreateTime is %I64u, expected > %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart - 100000000LL); 127c2c66affSColin Finck ok(Times1.ExitTime.QuadPart == 0, 128c2c66affSColin Finck "ExitTime is %I64u, expected 0\n", Times1.ExitTime.QuadPart); 129c2c66affSColin Finck ok(Times1.KernelTime.QuadPart != 0, "KernelTime is 0\n"); 130e26c8bc6STimo Kreuzer ros_skip_flaky 131c2c66affSColin Finck ok(Times1.UserTime.QuadPart != 0, "UserTime is 0\n"); 132c2c66affSColin Finck 133c2c66affSColin Finck /* Do some busy waiting to increase UserTime */ 134c2c66affSColin Finck do 135c2c66affSColin Finck { 136c2c66affSColin Finck Status = NtQuerySystemTime(&Time2); 137c2c66affSColin Finck if (!NT_SUCCESS(Status)) 138c2c66affSColin Finck { 139c2c66affSColin Finck ok(0, "NtQuerySystemTime failed with %lx\n", Status); 140c2c66affSColin Finck break; 141c2c66affSColin Finck } 142c2c66affSColin Finck } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME); 143c2c66affSColin Finck 144c2c66affSColin Finck /* Again, this time with a return length */ 145c2c66affSColin Finck Length = 0x55555555; 146c2c66affSColin Finck RtlFillMemory(&Times2, sizeof(Times2), 0x55); 147c2c66affSColin Finck Status = NtQueryInformationProcess(NtCurrentProcess(), 148c2c66affSColin Finck ProcessTimes, 149c2c66affSColin Finck &Times2, 150c2c66affSColin Finck sizeof(KERNEL_USER_TIMES), 151c2c66affSColin Finck &Length); 152c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 153c2c66affSColin Finck ok_dec(Length, sizeof(KERNEL_USER_TIMES)); 154c2c66affSColin Finck ok(Times1.CreateTime.QuadPart == Times2.CreateTime.QuadPart, 155c2c66affSColin Finck "CreateTimes not equal: %I64u != %I64u\n", Times1.CreateTime.QuadPart, Times2.CreateTime.QuadPart); 156c2c66affSColin Finck ok(Times2.ExitTime.QuadPart == 0, 157c2c66affSColin Finck "ExitTime is %I64u, expected 0\n", Times2.ExitTime.QuadPart); 158c2c66affSColin Finck ok(Times2.KernelTime.QuadPart != 0, "KernelTime is 0\n"); 159c2c66affSColin Finck ok(Times2.UserTime.QuadPart != 0, "UserTime is 0\n"); 160c2c66affSColin Finck 161c2c66affSColin Finck /* Compare the two sets of KernelTime/UserTime values */ 162c2c66affSColin Finck Status = NtQuerySystemTime(&Time2); 163c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 164c2c66affSColin Finck /* Time values must have increased */ 165c2c66affSColin Finck ok(Times2.KernelTime.QuadPart > Times1.KernelTime.QuadPart, 166c2c66affSColin Finck "KernelTime values inconsistent. Expected %I64u > %I64u\n", Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart); 167e26c8bc6STimo Kreuzer ros_skip_flaky 168c2c66affSColin Finck ok(Times2.UserTime.QuadPart > Times1.UserTime.QuadPart, 169c2c66affSColin Finck "UserTime values inconsistent. Expected %I64u > %I64u\n", Times2.UserTime.QuadPart, Times1.UserTime.QuadPart); 170c2c66affSColin Finck /* They can't have increased by more than wall clock time difference (we only have one thread) */ 171e26c8bc6STimo Kreuzer ros_skip_flaky 172c2c66affSColin Finck ok(Times2.KernelTime.QuadPart - Times1.KernelTime.QuadPart < Time2.QuadPart - Time1.QuadPart, 173c2c66affSColin Finck "KernelTime values inconsistent. Expected %I64u - %I64u < %I64u\n", 174c2c66affSColin Finck Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart, Time2.QuadPart - Time1.QuadPart); 175c2c66affSColin Finck ok(Times2.UserTime.QuadPart - Times1.UserTime.QuadPart < Time2.QuadPart - Time1.QuadPart, 176c2c66affSColin Finck "UserTime values inconsistent. Expected %I64u - %I64u < %I64u\n", 177c2c66affSColin Finck Times2.UserTime.QuadPart, Times1.UserTime.QuadPart, Time2.QuadPart - Time1.QuadPart); 178c2c66affSColin Finck 179c2c66affSColin Finck trace("KernelTime1 = %I64u\n", Times1.KernelTime.QuadPart); 180c2c66affSColin Finck trace("KernelTime2 = %I64u\n", Times2.KernelTime.QuadPart); 181c2c66affSColin Finck trace("UserTime1 = %I64u\n", Times1.UserTime.QuadPart); 182c2c66affSColin Finck trace("UserTime2 = %I64u\n", Times2.UserTime.QuadPart); 183c2c66affSColin Finck 184c2c66affSColin Finck /* TODO: Test ExitTime on a terminated process */ 185c2c66affSColin Finck #undef SPIN_TIME 186c2c66affSColin Finck } 187c2c66affSColin Finck 188fcb15638SBișoc George static 189fcb15638SBișoc George void 190fcb15638SBișoc George Test_ProcessPriorityClassAlignment(void) 191fcb15638SBișoc George { 192fcb15638SBișoc George NTSTATUS Status; 193fcb15638SBișoc George PPROCESS_PRIORITY_CLASS ProcPriority; 194fcb15638SBișoc George 195fcb15638SBișoc George /* Allocate some memory for the priority class structure */ 196fcb15638SBișoc George ProcPriority = malloc(sizeof(PROCESS_PRIORITY_CLASS)); 197fcb15638SBișoc George if (ProcPriority == NULL) 198fcb15638SBișoc George { 199fcb15638SBișoc George skip("Failed to allocate memory for PROCESS_PRIORITY_CLASS!\n"); 200fcb15638SBișoc George return; 201fcb15638SBișoc George } 202fcb15638SBișoc George 203fcb15638SBișoc George /* 204fcb15638SBișoc George * Initialize the PriorityClass member to ensure the test won't randomly succeed (if such data is uninitialized). 205fcb15638SBișoc George * Filling 85 to the data member makes sure that if the test fails continously then NtQueryInformationProcess() 206fcb15638SBișoc George * didn't initialize the structure with data. 207fcb15638SBișoc George */ 208fcb15638SBișoc George RtlFillMemory(&ProcPriority->PriorityClass, sizeof(ProcPriority->PriorityClass), 0x55); 209fcb15638SBișoc George 210fcb15638SBișoc George /* Unaligned buffer -- wrong size */ 211fcb15638SBișoc George Status = NtQueryInformationProcess(NtCurrentProcess(), 212fcb15638SBișoc George ProcessPriorityClass, 213fcb15638SBișoc George (PVOID)1, 214fcb15638SBișoc George 0, 215fcb15638SBișoc George NULL); 216fcb15638SBișoc George ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 217fcb15638SBișoc George 218fcb15638SBișoc George /* Unaligned buffer -- correct size */ 219fcb15638SBișoc George Status = NtQueryInformationProcess(NtCurrentProcess(), 220fcb15638SBișoc George ProcessPriorityClass, 221fcb15638SBișoc George (PVOID)1, 222fcb15638SBișoc George sizeof(PROCESS_PRIORITY_CLASS), 223fcb15638SBișoc George NULL); 224fcb15638SBișoc George ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 225fcb15638SBișoc George 226fcb15638SBișoc George /* Unaligned buffer -- wrong size (but this time do with an alignment of 2) */ 227fcb15638SBișoc George Status = NtQueryInformationProcess(NtCurrentProcess(), 228fcb15638SBișoc George ProcessPriorityClass, 229fcb15638SBișoc George (PVOID)2, 230fcb15638SBișoc George 0, 231fcb15638SBișoc George NULL); 232fcb15638SBișoc George ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 233fcb15638SBișoc George 234fcb15638SBișoc George /* Unaligned buffer -- correct size (but this time do with an alignment of 2) */ 235fcb15638SBișoc George Status = NtQueryInformationProcess(NtCurrentProcess(), 236fcb15638SBișoc George ProcessPriorityClass, 237fcb15638SBișoc George (PVOID)2, 238fcb15638SBișoc George sizeof(PROCESS_PRIORITY_CLASS), 239fcb15638SBișoc George NULL); 240fcb15638SBișoc George ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 241fcb15638SBișoc George 242fcb15638SBișoc George /* Do not care for the length but expect to return the priority class */ 243fcb15638SBișoc George Status = NtQueryInformationProcess(NtCurrentProcess(), 244fcb15638SBișoc George ProcessPriorityClass, 245fcb15638SBișoc George ProcPriority, 246fcb15638SBișoc George sizeof(PROCESS_PRIORITY_CLASS), 247fcb15638SBișoc George NULL); 248fcb15638SBișoc George ok_hex(Status, STATUS_SUCCESS); 249fcb15638SBișoc George 250fcb15638SBișoc George /* Make sure the returned priority class is a valid number (non negative) but also it should be within the PROCESS_PRIORITY_CLASS range */ 251fcb15638SBișoc George ok(ProcPriority->PriorityClass > PROCESS_PRIORITY_CLASS_INVALID && ProcPriority->PriorityClass <= PROCESS_PRIORITY_CLASS_ABOVE_NORMAL, 252fcb15638SBișoc George "Expected a valid number from priority class range but got %d\n", ProcPriority->PriorityClass); 253fcb15638SBișoc George free(ProcPriority); 254fcb15638SBișoc George } 255fcb15638SBișoc George 256*38c01a84SGeorge Bișoc static 257*38c01a84SGeorge Bișoc void 258*38c01a84SGeorge Bișoc Test_ProcessWx86Information(void) 259*38c01a84SGeorge Bișoc { 260*38c01a84SGeorge Bișoc NTSTATUS Status; 261*38c01a84SGeorge Bișoc ULONG VdmPower = 1, ReturnLength; 262*38c01a84SGeorge Bișoc 263*38c01a84SGeorge Bișoc /* Everything is NULL */ 264*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NULL, 265*38c01a84SGeorge Bișoc ProcessWx86Information, 266*38c01a84SGeorge Bișoc NULL, 267*38c01a84SGeorge Bișoc 0, 268*38c01a84SGeorge Bișoc NULL); 269*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 270*38c01a84SGeorge Bișoc 271*38c01a84SGeorge Bișoc /* Given an invalid process handle */ 272*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NULL, 273*38c01a84SGeorge Bișoc ProcessWx86Information, 274*38c01a84SGeorge Bișoc &VdmPower, 275*38c01a84SGeorge Bișoc sizeof(VdmPower), 276*38c01a84SGeorge Bișoc NULL); 277*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_INVALID_HANDLE); 278*38c01a84SGeorge Bișoc 279*38c01a84SGeorge Bișoc /* Don't query anything */ 280*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NtCurrentProcess(), 281*38c01a84SGeorge Bișoc ProcessWx86Information, 282*38c01a84SGeorge Bișoc NULL, 283*38c01a84SGeorge Bișoc sizeof(VdmPower), 284*38c01a84SGeorge Bișoc NULL); 285*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_ACCESS_VIOLATION); 286*38c01a84SGeorge Bișoc 287*38c01a84SGeorge Bișoc /* The buffer is misaligned and information length is wrong */ 288*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NtCurrentProcess(), 289*38c01a84SGeorge Bișoc ProcessWx86Information, 290*38c01a84SGeorge Bișoc (PVOID)1, 291*38c01a84SGeorge Bișoc 0, 292*38c01a84SGeorge Bișoc NULL); 293*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 294*38c01a84SGeorge Bișoc 295*38c01a84SGeorge Bișoc /* The buffer is misaligned */ 296*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NtCurrentProcess(), 297*38c01a84SGeorge Bișoc ProcessWx86Information, 298*38c01a84SGeorge Bișoc (PVOID)1, 299*38c01a84SGeorge Bișoc sizeof(VdmPower), 300*38c01a84SGeorge Bișoc NULL); 301*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 302*38c01a84SGeorge Bișoc 303*38c01a84SGeorge Bișoc /* The buffer is misaligned -- try with an alignment size of 2 */ 304*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NtCurrentProcess(), 305*38c01a84SGeorge Bișoc ProcessWx86Information, 306*38c01a84SGeorge Bișoc (PVOID)2, 307*38c01a84SGeorge Bișoc sizeof(VdmPower), 308*38c01a84SGeorge Bișoc NULL); 309*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 310*38c01a84SGeorge Bișoc 311*38c01a84SGeorge Bișoc /* Query the VDM power */ 312*38c01a84SGeorge Bișoc Status = NtQueryInformationProcess(NtCurrentProcess(), 313*38c01a84SGeorge Bișoc ProcessWx86Information, 314*38c01a84SGeorge Bișoc &VdmPower, 315*38c01a84SGeorge Bișoc sizeof(VdmPower), 316*38c01a84SGeorge Bișoc &ReturnLength); 317*38c01a84SGeorge Bișoc ok_hex(Status, STATUS_SUCCESS); 318*38c01a84SGeorge Bișoc ok(ReturnLength != 0, "ReturnLength shouldn't be 0!\n"); 319*38c01a84SGeorge Bișoc ok(VdmPower == 0 || VdmPower == 1, "The VDM power value must be within the boundary between 0 and 1, not anything else! Got %lu\n", VdmPower); 320*38c01a84SGeorge Bișoc 321*38c01a84SGeorge Bișoc /* Trace the VDM power value and returned length */ 322*38c01a84SGeorge Bișoc trace("ReturnLength = %lu\n", ReturnLength); 323*38c01a84SGeorge Bișoc trace("VdmPower = %lu\n", VdmPower); 324*38c01a84SGeorge Bișoc } 325*38c01a84SGeorge Bișoc 326c2c66affSColin Finck START_TEST(NtQueryInformationProcess) 327c2c66affSColin Finck { 328c2c66affSColin Finck NTSTATUS Status; 329c2c66affSColin Finck 330c2c66affSColin Finck Status = NtQuerySystemTime(&TestStartTime); 331c2c66affSColin Finck ok_hex(Status, STATUS_SUCCESS); 332c2c66affSColin Finck 333c2c66affSColin Finck Test_ProcessTimes(); 334fcb15638SBișoc George Test_ProcessPriorityClassAlignment(); 335*38c01a84SGeorge Bișoc Test_ProcessWx86Information(); 336c2c66affSColin Finck } 337