1 /* 2 * PROJECT: ReactOS API tests 3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Tests for the NtQueryInformationProcess API 5 * PROGRAMMER: Thomas Faber <thomas.faber@reactos.org> 6 * George Bișoc <george.bisoc@reactos.org> 7 */ 8 9 #include "precomp.h" 10 #include <internal/ps_i.h> 11 12 static LARGE_INTEGER TestStartTime; 13 14 static 15 void 16 Test_ProcessTimes(void) 17 { 18 #define SPIN_TIME 1000000 19 NTSTATUS Status; 20 KERNEL_USER_TIMES Times1; 21 KERNEL_USER_TIMES Times2; 22 ULONG Length; 23 LARGE_INTEGER Time1, Time2; 24 25 /* Everything is NULL */ 26 Status = NtQueryInformationProcess(NULL, 27 ProcessTimes, 28 NULL, 29 0, 30 NULL); 31 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 32 33 /* Right size, invalid process */ 34 Status = NtQueryInformationProcess(NULL, 35 ProcessTimes, 36 NULL, 37 sizeof(KERNEL_USER_TIMES), 38 NULL); 39 ok_hex(Status, STATUS_INVALID_HANDLE); 40 41 /* Valid process, no buffer */ 42 Status = NtQueryInformationProcess(NtCurrentProcess(), 43 ProcessTimes, 44 NULL, 45 0, 46 NULL); 47 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 48 49 /* Unaligned buffer, wrong size */ 50 Status = NtQueryInformationProcess(NtCurrentProcess(), 51 ProcessTimes, 52 (PVOID)2, 53 0, 54 NULL); 55 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 56 57 /* Unaligned buffer, correct size */ 58 Status = NtQueryInformationProcess(NtCurrentProcess(), 59 ProcessTimes, 60 (PVOID)2, 61 sizeof(KERNEL_USER_TIMES), 62 NULL); 63 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 64 65 /* Buffer too small */ 66 Status = NtQueryInformationProcess(NtCurrentProcess(), 67 ProcessTimes, 68 NULL, 69 sizeof(KERNEL_USER_TIMES) - 1, 70 NULL); 71 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 72 73 /* Right buffer size but NULL pointer */ 74 Status = NtQueryInformationProcess(NtCurrentProcess(), 75 ProcessTimes, 76 NULL, 77 sizeof(KERNEL_USER_TIMES), 78 NULL); 79 ok_hex(Status, STATUS_ACCESS_VIOLATION); 80 81 /* Buffer too large */ 82 Status = NtQueryInformationProcess(NtCurrentProcess(), 83 ProcessTimes, 84 NULL, 85 sizeof(KERNEL_USER_TIMES) + 1, 86 NULL); 87 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 88 89 /* Buffer too small, ask for length */ 90 Length = 0x55555555; 91 Status = NtQueryInformationProcess(NtCurrentProcess(), 92 ProcessTimes, 93 NULL, 94 sizeof(KERNEL_USER_TIMES) - 1, 95 &Length); 96 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 97 ok_dec(Length, 0x55555555); 98 99 Status = NtQuerySystemTime(&Time1); 100 ok_hex(Status, STATUS_SUCCESS); 101 102 /* Do some busy waiting to increase UserTime */ 103 do 104 { 105 Status = NtQuerySystemTime(&Time2); 106 if (!NT_SUCCESS(Status)) 107 { 108 ok(0, "NtQuerySystemTime failed with %lx\n", Status); 109 break; 110 } 111 } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME); 112 113 /* Valid parameters, no return length */ 114 Status = NtQuerySystemTime(&Time1); 115 ok_hex(Status, STATUS_SUCCESS); 116 117 RtlFillMemory(&Times1, sizeof(Times1), 0x55); 118 Status = NtQueryInformationProcess(NtCurrentProcess(), 119 ProcessTimes, 120 &Times1, 121 sizeof(KERNEL_USER_TIMES), 122 NULL); 123 ok_hex(Status, STATUS_SUCCESS); 124 ok(Times1.CreateTime.QuadPart < TestStartTime.QuadPart, 125 "CreateTime is %I64u, expected < %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart); 126 ok(Times1.CreateTime.QuadPart > TestStartTime.QuadPart - 100000000LL, 127 "CreateTime is %I64u, expected > %I64u\n", Times1.CreateTime.QuadPart, TestStartTime.QuadPart - 100000000LL); 128 ok(Times1.ExitTime.QuadPart == 0, 129 "ExitTime is %I64u, expected 0\n", Times1.ExitTime.QuadPart); 130 ok(Times1.KernelTime.QuadPart != 0, "KernelTime is 0\n"); 131 ros_skip_flaky 132 ok(Times1.UserTime.QuadPart != 0, "UserTime is 0\n"); 133 134 /* Do some busy waiting to increase UserTime */ 135 do 136 { 137 Status = NtQuerySystemTime(&Time2); 138 if (!NT_SUCCESS(Status)) 139 { 140 ok(0, "NtQuerySystemTime failed with %lx\n", Status); 141 break; 142 } 143 } while (Time2.QuadPart - Time1.QuadPart < SPIN_TIME); 144 145 /* Again, this time with a return length */ 146 Length = 0x55555555; 147 RtlFillMemory(&Times2, sizeof(Times2), 0x55); 148 Status = NtQueryInformationProcess(NtCurrentProcess(), 149 ProcessTimes, 150 &Times2, 151 sizeof(KERNEL_USER_TIMES), 152 &Length); 153 ok_hex(Status, STATUS_SUCCESS); 154 ok_dec(Length, sizeof(KERNEL_USER_TIMES)); 155 ok(Times1.CreateTime.QuadPart == Times2.CreateTime.QuadPart, 156 "CreateTimes not equal: %I64u != %I64u\n", Times1.CreateTime.QuadPart, Times2.CreateTime.QuadPart); 157 ok(Times2.ExitTime.QuadPart == 0, 158 "ExitTime is %I64u, expected 0\n", Times2.ExitTime.QuadPart); 159 ok(Times2.KernelTime.QuadPart != 0, "KernelTime is 0\n"); 160 ok(Times2.UserTime.QuadPart != 0, "UserTime is 0\n"); 161 162 /* Compare the two sets of KernelTime/UserTime values */ 163 Status = NtQuerySystemTime(&Time2); 164 ok_hex(Status, STATUS_SUCCESS); 165 /* Time values must have increased */ 166 ok(Times2.KernelTime.QuadPart > Times1.KernelTime.QuadPart, 167 "KernelTime values inconsistent. Expected %I64u > %I64u\n", Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart); 168 ros_skip_flaky 169 ok(Times2.UserTime.QuadPart > Times1.UserTime.QuadPart, 170 "UserTime values inconsistent. Expected %I64u > %I64u\n", Times2.UserTime.QuadPart, Times1.UserTime.QuadPart); 171 /* They can't have increased by more than wall clock time difference (we only have one thread) */ 172 ros_skip_flaky 173 ok(Times2.KernelTime.QuadPart - Times1.KernelTime.QuadPart < Time2.QuadPart - Time1.QuadPart, 174 "KernelTime values inconsistent. Expected %I64u - %I64u < %I64u\n", 175 Times2.KernelTime.QuadPart, Times1.KernelTime.QuadPart, Time2.QuadPart - Time1.QuadPart); 176 ok(Times2.UserTime.QuadPart - Times1.UserTime.QuadPart < Time2.QuadPart - Time1.QuadPart, 177 "UserTime values inconsistent. Expected %I64u - %I64u < %I64u\n", 178 Times2.UserTime.QuadPart, Times1.UserTime.QuadPart, Time2.QuadPart - Time1.QuadPart); 179 180 trace("KernelTime1 = %I64u\n", Times1.KernelTime.QuadPart); 181 trace("KernelTime2 = %I64u\n", Times2.KernelTime.QuadPart); 182 trace("UserTime1 = %I64u\n", Times1.UserTime.QuadPart); 183 trace("UserTime2 = %I64u\n", Times2.UserTime.QuadPart); 184 185 /* TODO: Test ExitTime on a terminated process */ 186 #undef SPIN_TIME 187 } 188 189 static 190 void 191 Test_ProcessBasicInformation(void) 192 { 193 NTSTATUS Status; 194 ULONG Length; 195 PROCESS_BASIC_INFORMATION BasicInfo; 196 197 /* Everything is NULL */ 198 Status = NtQueryInformationProcess(NULL, 199 ProcessBasicInformation, 200 NULL, 201 0, 202 NULL); 203 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 204 205 /* Right size, invalid process handle */ 206 Status = NtQueryInformationProcess(NULL, 207 ProcessBasicInformation, 208 NULL, 209 sizeof(BasicInfo), 210 NULL); 211 ok_hex(Status, STATUS_INVALID_HANDLE); 212 213 /* Valid process handle, no buffer */ 214 Status = NtQueryInformationProcess(NtCurrentProcess(), 215 ProcessBasicInformation, 216 NULL, 217 0, 218 NULL); 219 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 220 221 /* Unaligned buffer, wrong size */ 222 Status = NtQueryInformationProcess(NtCurrentProcess(), 223 ProcessBasicInformation, 224 (PVOID)2, 225 0, 226 NULL); 227 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 228 229 /* Unaligned buffer, correct size */ 230 Status = NtQueryInformationProcess(NtCurrentProcess(), 231 ProcessBasicInformation, 232 (PVOID)2, 233 sizeof(BasicInfo), 234 NULL); 235 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 236 237 /* Buffer too small */ 238 Status = NtQueryInformationProcess(NtCurrentProcess(), 239 ProcessBasicInformation, 240 NULL, 241 sizeof(BasicInfo) - 1, 242 NULL); 243 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 244 245 /* Right buffer size but NULL pointer */ 246 Status = NtQueryInformationProcess(NtCurrentProcess(), 247 ProcessBasicInformation, 248 NULL, 249 sizeof(BasicInfo), 250 NULL); 251 ok_hex(Status, STATUS_ACCESS_VIOLATION); 252 253 /* Buffer too large */ 254 Status = NtQueryInformationProcess(NtCurrentProcess(), 255 ProcessBasicInformation, 256 NULL, 257 sizeof(BasicInfo) + 1, 258 NULL); 259 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 260 261 /* Buffer too small, ask for length */ 262 Length = 0x55555555; 263 Status = NtQueryInformationProcess(NtCurrentProcess(), 264 ProcessBasicInformation, 265 NULL, 266 sizeof(BasicInfo) - 1, 267 &Length); 268 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 269 ok_dec(Length, 0x55555555); 270 271 /* Valid parameters, no return length */ 272 RtlFillMemory(&BasicInfo, sizeof(BasicInfo), 0x55); 273 Status = NtQueryInformationProcess(NtCurrentProcess(), 274 ProcessBasicInformation, 275 &BasicInfo, 276 sizeof(BasicInfo), 277 NULL); 278 ok_hex(Status, STATUS_SUCCESS); 279 280 /* Trace the returned data (1) */ 281 trace("[1] BasicInfo.ExitStatus = %lx\n", BasicInfo.ExitStatus); 282 trace("[1] BasicInfo.PebBaseAddress = %p\n", BasicInfo.PebBaseAddress); 283 trace("[1] BasicInfo.AffinityMask = %Ix\n", BasicInfo.AffinityMask); 284 trace("[1] BasicInfo.BasePriority = %ld\n", BasicInfo.BasePriority); 285 trace("[1] BasicInfo.UniqueProcessId = %Iu\n", BasicInfo.UniqueProcessId); 286 trace("[1] BasicInfo.InheritedFromUniqueProcessId = %Iu\n", BasicInfo.InheritedFromUniqueProcessId); 287 288 /* Again, this time with a return length */ 289 Length = 0x55555555; 290 RtlFillMemory(&BasicInfo, sizeof(BasicInfo), 0x55); 291 Status = NtQueryInformationProcess(NtCurrentProcess(), 292 ProcessBasicInformation, 293 &BasicInfo, 294 sizeof(BasicInfo), 295 &Length); 296 ok_hex(Status, STATUS_SUCCESS); 297 ok_dec(Length, sizeof(BasicInfo)); 298 299 /* Trace the returned data (2) */ 300 trace("[2] BasicInfo.ExitStatus = %lx\n", BasicInfo.ExitStatus); 301 trace("[2] BasicInfo.PebBaseAddress = %p\n", BasicInfo.PebBaseAddress); 302 trace("[2] BasicInfo.AffinityMask = %Ix\n", BasicInfo.AffinityMask); 303 trace("[2] BasicInfo.BasePriority = %ld\n", BasicInfo.BasePriority); 304 trace("[2] BasicInfo.UniqueProcessId = %Iu\n", BasicInfo.UniqueProcessId); 305 trace("[2] BasicInfo.InheritedFromUniqueProcessId = %Iu\n", BasicInfo.InheritedFromUniqueProcessId); 306 } 307 308 static 309 void 310 Test_ProcessQuotaLimits(void) 311 { 312 NTSTATUS Status; 313 ULONG Length; 314 QUOTA_LIMITS QuotaLimits; 315 316 /* Everything is NULL */ 317 Status = NtQueryInformationProcess(NULL, 318 ProcessQuotaLimits, 319 NULL, 320 0, 321 NULL); 322 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 323 324 /* Right size, invalid process handle */ 325 Status = NtQueryInformationProcess(NULL, 326 ProcessQuotaLimits, 327 NULL, 328 sizeof(QuotaLimits), 329 NULL); 330 ok_hex(Status, STATUS_INVALID_HANDLE); 331 332 /* Valid process handle, no buffer */ 333 Status = NtQueryInformationProcess(NtCurrentProcess(), 334 ProcessQuotaLimits, 335 NULL, 336 0, 337 NULL); 338 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 339 340 /* Unaligned buffer, wrong size */ 341 Status = NtQueryInformationProcess(NtCurrentProcess(), 342 ProcessQuotaLimits, 343 (PVOID)2, 344 0, 345 NULL); 346 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 347 348 /* Unaligned buffer, correct size */ 349 Status = NtQueryInformationProcess(NtCurrentProcess(), 350 ProcessQuotaLimits, 351 (PVOID)2, 352 sizeof(QuotaLimits), 353 NULL); 354 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 355 356 /* Buffer too small */ 357 Status = NtQueryInformationProcess(NtCurrentProcess(), 358 ProcessQuotaLimits, 359 NULL, 360 sizeof(QuotaLimits) - 1, 361 NULL); 362 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 363 364 /* Right buffer size but NULL pointer */ 365 Status = NtQueryInformationProcess(NtCurrentProcess(), 366 ProcessQuotaLimits, 367 NULL, 368 sizeof(QuotaLimits), 369 NULL); 370 ok_hex(Status, STATUS_ACCESS_VIOLATION); 371 372 /* Buffer too large */ 373 Status = NtQueryInformationProcess(NtCurrentProcess(), 374 ProcessQuotaLimits, 375 NULL, 376 sizeof(QuotaLimits) + 1, 377 NULL); 378 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 379 380 /* Buffer too small, ask for length */ 381 Length = 0x55555555; 382 Status = NtQueryInformationProcess(NtCurrentProcess(), 383 ProcessQuotaLimits, 384 NULL, 385 sizeof(QuotaLimits) - 1, 386 &Length); 387 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 388 ok_dec(Length, 0x55555555); 389 390 /* Valid parameters, no return length */ 391 RtlFillMemory(&QuotaLimits, sizeof(QuotaLimits), 0x55); 392 Status = NtQueryInformationProcess(NtCurrentProcess(), 393 ProcessQuotaLimits, 394 &QuotaLimits, 395 sizeof(QuotaLimits), 396 NULL); 397 ok_hex(Status, STATUS_SUCCESS); 398 399 /* Trace the returned data (1) */ 400 trace("[1] QuotaLimits.PagedPoolLimit = %Iu\n", QuotaLimits.PagedPoolLimit); 401 trace("[1] QuotaLimits.NonPagedPoolLimit = %Iu\n", QuotaLimits.NonPagedPoolLimit); 402 trace("[1] QuotaLimits.MinimumWorkingSetSize = %Iu\n", QuotaLimits.MinimumWorkingSetSize); 403 trace("[1] QuotaLimits.MaximumWorkingSetSize = %Iu\n", QuotaLimits.MaximumWorkingSetSize); 404 trace("[1] QuotaLimits.PagefileLimit = %Iu\n", QuotaLimits.PagefileLimit); 405 trace("[1] QuotaLimits.TimeLimit = %I64d\n", QuotaLimits.TimeLimit.QuadPart); 406 407 /* Again, this time with a return length */ 408 Length = 0x55555555; 409 RtlFillMemory(&QuotaLimits, sizeof(QuotaLimits), 0x55); 410 Status = NtQueryInformationProcess(NtCurrentProcess(), 411 ProcessQuotaLimits, 412 &QuotaLimits, 413 sizeof(QuotaLimits), 414 &Length); 415 ok_hex(Status, STATUS_SUCCESS); 416 ok_dec(Length, sizeof(QuotaLimits)); 417 418 /* Trace the returned data (2) */ 419 trace("[2] QuotaLimits.PagedPoolLimit = %Iu\n", QuotaLimits.PagedPoolLimit); 420 trace("[2] QuotaLimits.NonPagedPoolLimit = %Iu\n", QuotaLimits.NonPagedPoolLimit); 421 trace("[2] QuotaLimits.MinimumWorkingSetSize = %Iu\n", QuotaLimits.MinimumWorkingSetSize); 422 trace("[2] QuotaLimits.MaximumWorkingSetSize = %Iu\n", QuotaLimits.MaximumWorkingSetSize); 423 trace("[2] QuotaLimits.PagefileLimit = %Iu\n", QuotaLimits.PagefileLimit); 424 trace("[2] QuotaLimits.TimeLimit = %I64d\n", QuotaLimits.TimeLimit.QuadPart); 425 } 426 427 static 428 void 429 Test_ProcessQuotaLimitsEx(void) 430 { 431 NTSTATUS Status; 432 ULONG Length; 433 QUOTA_LIMITS_EX QuotaLimitsEx; 434 435 /* Right size, invalid process handle */ 436 Status = NtQueryInformationProcess(NULL, 437 ProcessQuotaLimits, 438 NULL, 439 sizeof(QuotaLimitsEx), 440 NULL); 441 ok_hex(Status, STATUS_INVALID_HANDLE); 442 443 /* Unaligned buffer, correct size */ 444 Status = NtQueryInformationProcess(NtCurrentProcess(), 445 ProcessQuotaLimits, 446 (PVOID)2, 447 sizeof(QuotaLimitsEx), 448 NULL); 449 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 450 451 /* Buffer too small */ 452 Status = NtQueryInformationProcess(NtCurrentProcess(), 453 ProcessQuotaLimits, 454 NULL, 455 sizeof(QuotaLimitsEx) - 1, 456 NULL); 457 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 458 459 /* Right buffer size but NULL pointer */ 460 Status = NtQueryInformationProcess(NtCurrentProcess(), 461 ProcessQuotaLimits, 462 NULL, 463 sizeof(QuotaLimitsEx), 464 NULL); 465 ok_hex(Status, STATUS_ACCESS_VIOLATION); 466 467 /* Buffer too large */ 468 Status = NtQueryInformationProcess(NtCurrentProcess(), 469 ProcessQuotaLimits, 470 NULL, 471 sizeof(QuotaLimitsEx) + 1, 472 NULL); 473 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 474 475 /* Buffer too small, ask for length */ 476 Length = 0x55555555; 477 Status = NtQueryInformationProcess(NtCurrentProcess(), 478 ProcessQuotaLimits, 479 NULL, 480 sizeof(QuotaLimitsEx) - 1, 481 &Length); 482 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 483 ok_dec(Length, 0x55555555); 484 485 /* Valid parameters, no return length */ 486 RtlFillMemory(&QuotaLimitsEx, sizeof(QuotaLimitsEx), 0x55); 487 Status = NtQueryInformationProcess(NtCurrentProcess(), 488 ProcessQuotaLimits, 489 &QuotaLimitsEx, 490 sizeof(QuotaLimitsEx), 491 NULL); 492 ok_hex(Status, STATUS_SUCCESS); 493 494 /* Trace the returned data (1) */ 495 trace("[1] QuotaLimitsEx.PagedPoolLimit = %Iu\n", QuotaLimitsEx.PagedPoolLimit); 496 trace("[1] QuotaLimitsEx.NonPagedPoolLimit = %Iu\n", QuotaLimitsEx.NonPagedPoolLimit); 497 trace("[1] QuotaLimitsEx.MinimumWorkingSetSize = %Iu\n", QuotaLimitsEx.MinimumWorkingSetSize); 498 trace("[1] QuotaLimitsEx.MaximumWorkingSetSize = %Iu\n", QuotaLimitsEx.MaximumWorkingSetSize); 499 trace("[1] QuotaLimitsEx.PagefileLimit = %Iu\n", QuotaLimitsEx.PagefileLimit); 500 trace("[1] QuotaLimitsEx.TimeLimit = %I64d\n", QuotaLimitsEx.TimeLimit.QuadPart); 501 //trace("[1] QuotaLimitsEx.WorkingSetLimit = %Iu\n", QuotaLimitsEx.WorkingSetLimit); // Not used on Win2k3 502 trace("[1] QuotaLimitsEx.Flags = %lx\n", QuotaLimitsEx.Flags); 503 trace("[1] QuotaLimitsEx.CpuRateLimit.RateData = %lx\n", QuotaLimitsEx.CpuRateLimit.RateData); 504 505 /* Again, this time with a return length */ 506 Length = 0x55555555; 507 RtlFillMemory(&QuotaLimitsEx, sizeof(QuotaLimitsEx), 0x55); 508 Status = NtQueryInformationProcess(NtCurrentProcess(), 509 ProcessQuotaLimits, 510 &QuotaLimitsEx, 511 sizeof(QuotaLimitsEx), 512 &Length); 513 ok_hex(Status, STATUS_SUCCESS); 514 ok_dec(Length, sizeof(QuotaLimitsEx)); 515 516 /* Trace the returned data (2) */ 517 trace("[2] QuotaLimitsEx.PagedPoolLimit = %Iu\n", QuotaLimitsEx.PagedPoolLimit); 518 trace("[2] QuotaLimitsEx.NonPagedPoolLimit = %Iu\n", QuotaLimitsEx.NonPagedPoolLimit); 519 trace("[2] QuotaLimitsEx.MinimumWorkingSetSize = %Iu\n", QuotaLimitsEx.MinimumWorkingSetSize); 520 trace("[2] QuotaLimitsEx.MaximumWorkingSetSize = %Iu\n", QuotaLimitsEx.MaximumWorkingSetSize); 521 trace("[2] QuotaLimitsEx.PagefileLimit = %Iu\n", QuotaLimitsEx.PagefileLimit); 522 trace("[2] QuotaLimitsEx.TimeLimit = %I64d\n", QuotaLimitsEx.TimeLimit.QuadPart); 523 //trace("[2] QuotaLimitsEx.WorkingSetLimit = %Iu\n", QuotaLimitsEx.WorkingSetLimit); // Not used on Win2k3 524 trace("[2] QuotaLimitsEx.Flags = %lx\n", QuotaLimitsEx.Flags); 525 trace("[2] QuotaLimitsEx.CpuRateLimit.RateData = %lx\n", QuotaLimitsEx.CpuRateLimit.RateData); 526 } 527 528 static 529 void 530 Test_ProcessPriorityClassAlignment(void) 531 { 532 NTSTATUS Status; 533 PPROCESS_PRIORITY_CLASS ProcPriority; 534 535 /* Allocate some memory for the priority class structure */ 536 ProcPriority = malloc(sizeof(PROCESS_PRIORITY_CLASS)); 537 if (ProcPriority == NULL) 538 { 539 skip("Failed to allocate memory for PROCESS_PRIORITY_CLASS!\n"); 540 return; 541 } 542 543 /* 544 * Initialize the PriorityClass member to ensure the test won't randomly succeed (if such data is uninitialized). 545 * Filling 85 to the data member makes sure that if the test fails continously then NtQueryInformationProcess() 546 * didn't initialize the structure with data. 547 */ 548 RtlFillMemory(&ProcPriority->PriorityClass, sizeof(ProcPriority->PriorityClass), 0x55); 549 550 /* Unaligned buffer -- wrong size */ 551 Status = NtQueryInformationProcess(NtCurrentProcess(), 552 ProcessPriorityClass, 553 (PVOID)1, 554 0, 555 NULL); 556 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 557 558 /* Unaligned buffer -- correct size */ 559 Status = NtQueryInformationProcess(NtCurrentProcess(), 560 ProcessPriorityClass, 561 (PVOID)1, 562 sizeof(PROCESS_PRIORITY_CLASS), 563 NULL); 564 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 565 566 /* Unaligned buffer -- wrong size (but this time do with an alignment of 2) */ 567 Status = NtQueryInformationProcess(NtCurrentProcess(), 568 ProcessPriorityClass, 569 (PVOID)2, 570 0, 571 NULL); 572 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 573 574 /* Unaligned buffer -- correct size (but this time do with an alignment of 2) */ 575 Status = NtQueryInformationProcess(NtCurrentProcess(), 576 ProcessPriorityClass, 577 (PVOID)2, 578 sizeof(PROCESS_PRIORITY_CLASS), 579 NULL); 580 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 581 582 /* Do not care for the length but expect to return the priority class */ 583 Status = NtQueryInformationProcess(NtCurrentProcess(), 584 ProcessPriorityClass, 585 ProcPriority, 586 sizeof(PROCESS_PRIORITY_CLASS), 587 NULL); 588 ok_hex(Status, STATUS_SUCCESS); 589 590 /* Make sure the returned priority class is a valid number (non negative) but also it should be within the PROCESS_PRIORITY_CLASS range */ 591 ok(ProcPriority->PriorityClass > PROCESS_PRIORITY_CLASS_INVALID && ProcPriority->PriorityClass <= PROCESS_PRIORITY_CLASS_ABOVE_NORMAL, 592 "Expected a valid number from priority class range but got %d\n", ProcPriority->PriorityClass); 593 free(ProcPriority); 594 } 595 596 static 597 void 598 Test_ProcessWx86Information(void) 599 { 600 NTSTATUS Status; 601 ULONG VdmPower = 1, ReturnLength; 602 603 /* Everything is NULL */ 604 Status = NtQueryInformationProcess(NULL, 605 ProcessWx86Information, 606 NULL, 607 0, 608 NULL); 609 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 610 611 /* Given an invalid process handle */ 612 Status = NtQueryInformationProcess(NULL, 613 ProcessWx86Information, 614 &VdmPower, 615 sizeof(VdmPower), 616 NULL); 617 ok_hex(Status, STATUS_INVALID_HANDLE); 618 619 /* Don't query anything */ 620 Status = NtQueryInformationProcess(NtCurrentProcess(), 621 ProcessWx86Information, 622 NULL, 623 sizeof(VdmPower), 624 NULL); 625 ok_hex(Status, STATUS_ACCESS_VIOLATION); 626 627 /* The buffer is misaligned and information length is wrong */ 628 Status = NtQueryInformationProcess(NtCurrentProcess(), 629 ProcessWx86Information, 630 (PVOID)1, 631 0, 632 NULL); 633 ok_hex(Status, STATUS_INFO_LENGTH_MISMATCH); 634 635 /* The buffer is misaligned */ 636 Status = NtQueryInformationProcess(NtCurrentProcess(), 637 ProcessWx86Information, 638 (PVOID)1, 639 sizeof(VdmPower), 640 NULL); 641 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 642 643 /* The buffer is misaligned -- try with an alignment size of 2 */ 644 Status = NtQueryInformationProcess(NtCurrentProcess(), 645 ProcessWx86Information, 646 (PVOID)2, 647 sizeof(VdmPower), 648 NULL); 649 ok_hex(Status, STATUS_DATATYPE_MISALIGNMENT); 650 651 /* Query the VDM power */ 652 Status = NtQueryInformationProcess(NtCurrentProcess(), 653 ProcessWx86Information, 654 &VdmPower, 655 sizeof(VdmPower), 656 NULL); 657 ok_hex(Status, STATUS_SUCCESS); 658 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); 659 660 /* Same but with ReturnLength */ 661 Status = NtQueryInformationProcess(NtCurrentProcess(), 662 ProcessWx86Information, 663 &VdmPower, 664 sizeof(VdmPower), 665 &ReturnLength); 666 ok_hex(Status, STATUS_SUCCESS); 667 ok(ReturnLength != 0, "ReturnLength shouldn't be 0!\n"); 668 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); 669 670 /* Trace the VDM power value and returned length */ 671 trace("ReturnLength = %lu\n", ReturnLength); 672 trace("VdmPower = %lu\n", VdmPower); 673 } 674 675 static 676 void 677 Test_ProcQueryAlignmentProbe(void) 678 { 679 ULONG InfoClass; 680 681 /* Iterate over the process info classes and begin the tests */ 682 for (InfoClass = 0; InfoClass < _countof(PsProcessInfoClass); InfoClass++) 683 { 684 /* The buffer is misaligned */ 685 QuerySetProcessValidator(QUERY, 686 InfoClass, 687 (PVOID)(ULONG_PTR)1, 688 PsProcessInfoClass[InfoClass].RequiredSizeQUERY, 689 STATUS_DATATYPE_MISALIGNMENT); 690 691 /* We query an invalid buffer address */ 692 QuerySetProcessValidator(QUERY, 693 InfoClass, 694 (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentQUERY, 695 PsProcessInfoClass[InfoClass].RequiredSizeQUERY, 696 STATUS_ACCESS_VIOLATION); 697 698 /* The information length is wrong */ 699 QuerySetProcessValidator(QUERY, 700 InfoClass, 701 (PVOID)(ULONG_PTR)PsProcessInfoClass[InfoClass].AlignmentQUERY, 702 PsProcessInfoClass[InfoClass].RequiredSizeQUERY - 1, 703 STATUS_INFO_LENGTH_MISMATCH); 704 } 705 } 706 707 START_TEST(NtQueryInformationProcess) 708 { 709 NTSTATUS Status; 710 711 /* Make sure that some time has passed since process creation, even if the resolution of our NtQuerySystemTime is low. */ 712 Sleep(1); 713 714 Status = NtQuerySystemTime(&TestStartTime); 715 ok_hex(Status, STATUS_SUCCESS); 716 717 Test_ProcessTimes(); 718 Test_ProcessBasicInformation(); 719 Test_ProcessQuotaLimits(); 720 Test_ProcessQuotaLimitsEx(); 721 Test_ProcessPriorityClassAlignment(); 722 Test_ProcessWx86Information(); 723 Test_ProcQueryAlignmentProbe(); 724 } 725