1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntoskrnl/ex/sysinfo.c 5 * PURPOSE: System information functions 6 * 7 * PROGRAMMERS: David Welch (welch@mcmail.com) 8 * Aleksey Bragin (aleksey@reactos.org) 9 */ 10 11 /* INCLUDES *****************************************************************/ 12 13 #include <ntoskrnl.h> 14 #include <wmidata.h> 15 #include <wmistr.h> 16 #define NDEBUG 17 #include <debug.h> 18 19 /* The maximum size of an environment value (in bytes) */ 20 #define MAX_ENVVAL_SIZE 1024 21 22 #define SIG_ACPI 0x41435049 23 #define SIG_FIRM 0x4649524D 24 #define SIG_RSMB 0x52534D42 25 26 extern LIST_ENTRY HandleTableListHead; 27 extern EX_PUSH_LOCK HandleTableListLock; 28 29 FAST_MUTEX ExpEnvironmentLock; 30 ERESOURCE ExpFirmwareTableResource; 31 LIST_ENTRY ExpFirmwareTableProviderListHead; 32 33 FORCEINLINE 34 NTSTATUS 35 ExpConvertLdrModuleToRtlModule(IN ULONG ModuleCount, 36 IN PLDR_DATA_TABLE_ENTRY LdrEntry, 37 OUT PRTL_PROCESS_MODULE_INFORMATION ModuleInfo) 38 { 39 PCHAR p; 40 NTSTATUS Status; 41 ANSI_STRING ModuleName; 42 43 /* Fill it out */ 44 ModuleInfo->MappedBase = NULL; 45 ModuleInfo->ImageBase = LdrEntry->DllBase; 46 ModuleInfo->ImageSize = LdrEntry->SizeOfImage; 47 ModuleInfo->Flags = LdrEntry->Flags; 48 ModuleInfo->LoadCount = LdrEntry->LoadCount; 49 ModuleInfo->LoadOrderIndex = (USHORT)ModuleCount; 50 ModuleInfo->InitOrderIndex = 0; 51 52 /* Setup name */ 53 RtlInitEmptyAnsiString(&ModuleName, 54 ModuleInfo->FullPathName, 55 sizeof(ModuleInfo->FullPathName)); 56 57 /* Convert it */ 58 Status = RtlUnicodeStringToAnsiString(&ModuleName, 59 &LdrEntry->FullDllName, 60 FALSE); 61 if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW)) 62 { 63 /* Calculate offset to name */ 64 p = ModuleName.Buffer + ModuleName.Length; 65 while ((p > ModuleName.Buffer) && (*--p)) 66 { 67 /* Check if we found the separator */ 68 if (*p == OBJ_NAME_PATH_SEPARATOR) 69 { 70 /* We did, break out */ 71 p++; 72 break; 73 } 74 } 75 76 /* Set the offset */ 77 ModuleInfo->OffsetToFileName = (USHORT)(p - ModuleName.Buffer); 78 } 79 else 80 { 81 /* Return empty name */ 82 ModuleInfo->FullPathName[0] = ANSI_NULL; 83 ModuleInfo->OffsetToFileName = 0; 84 } 85 86 return Status; 87 } 88 89 NTSTATUS 90 NTAPI 91 ExpQueryModuleInformation(IN PLIST_ENTRY KernelModeList, 92 IN PLIST_ENTRY UserModeList, 93 OUT PRTL_PROCESS_MODULES Modules, 94 IN ULONG Length, 95 OUT PULONG ReturnLength) 96 { 97 NTSTATUS Status = STATUS_SUCCESS; 98 ULONG RequiredLength; 99 PRTL_PROCESS_MODULE_INFORMATION ModuleInfo; 100 PLDR_DATA_TABLE_ENTRY LdrEntry; 101 ULONG ModuleCount = 0; 102 PLIST_ENTRY NextEntry; 103 104 /* Setup defaults */ 105 RequiredLength = FIELD_OFFSET(RTL_PROCESS_MODULES, Modules); 106 ModuleInfo = &Modules->Modules[0]; 107 108 /* Loop the kernel list */ 109 NextEntry = KernelModeList->Flink; 110 while (NextEntry != KernelModeList) 111 { 112 /* Get the entry */ 113 LdrEntry = CONTAINING_RECORD(NextEntry, 114 LDR_DATA_TABLE_ENTRY, 115 InLoadOrderLinks); 116 117 /* Update size and check if we can manage one more entry */ 118 RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION); 119 if (Length >= RequiredLength) 120 { 121 Status = ExpConvertLdrModuleToRtlModule(ModuleCount, 122 LdrEntry, 123 ModuleInfo); 124 125 /* Go to the next module */ 126 ModuleInfo++; 127 } 128 else 129 { 130 /* Set error code */ 131 Status = STATUS_INFO_LENGTH_MISMATCH; 132 } 133 134 /* Update count and move to next entry */ 135 ModuleCount++; 136 NextEntry = NextEntry->Flink; 137 } 138 139 /* Check if caller also wanted user modules */ 140 if (UserModeList) 141 { 142 NextEntry = UserModeList->Flink; 143 while (NextEntry != UserModeList) 144 { 145 /* Get the entry */ 146 LdrEntry = CONTAINING_RECORD(NextEntry, 147 LDR_DATA_TABLE_ENTRY, 148 InLoadOrderLinks); 149 150 /* Update size and check if we can manage one more entry */ 151 RequiredLength += sizeof(RTL_PROCESS_MODULE_INFORMATION); 152 if (Length >= RequiredLength) 153 { 154 Status = ExpConvertLdrModuleToRtlModule(ModuleCount, 155 LdrEntry, 156 ModuleInfo); 157 158 /* Go to the next module */ 159 ModuleInfo++; 160 } 161 else 162 { 163 /* Set error code */ 164 Status = STATUS_INFO_LENGTH_MISMATCH; 165 } 166 167 /* Update count and move to next entry */ 168 ModuleCount++; 169 NextEntry = NextEntry->Flink; 170 } 171 } 172 173 /* Update return length */ 174 if (ReturnLength) *ReturnLength = RequiredLength; 175 176 /* Validate the length again */ 177 if (Length >= FIELD_OFFSET(RTL_PROCESS_MODULES, Modules)) 178 { 179 /* Set the final count */ 180 Modules->NumberOfModules = ModuleCount; 181 } 182 else 183 { 184 /* Otherwise, we failed */ 185 Status = STATUS_INFO_LENGTH_MISMATCH; 186 } 187 188 /* Done */ 189 return Status; 190 } 191 192 VOID 193 NTAPI 194 ExUnlockUserBuffer(PMDL Mdl) 195 { 196 MmUnlockPages(Mdl); 197 ExFreePoolWithTag(Mdl, TAG_MDL); 198 } 199 200 NTSTATUS 201 NTAPI 202 ExLockUserBuffer( 203 PVOID BaseAddress, 204 ULONG Length, 205 KPROCESSOR_MODE AccessMode, 206 LOCK_OPERATION Operation, 207 PVOID *MappedSystemVa, 208 PMDL *OutMdl) 209 { 210 PMDL Mdl; 211 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 212 213 *MappedSystemVa = NULL; 214 *OutMdl = NULL; 215 216 /* Allocate an MDL for the buffer */ 217 Mdl = IoAllocateMdl(BaseAddress, Length, FALSE, TRUE, NULL); 218 if (Mdl == NULL) 219 { 220 return STATUS_INSUFFICIENT_RESOURCES; 221 } 222 223 /* Enter SEH for probing */ 224 _SEH2_TRY 225 { 226 MmProbeAndLockPages(Mdl, AccessMode, Operation); 227 } 228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 229 { 230 ExFreePoolWithTag(Mdl, TAG_MDL); 231 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 232 } 233 _SEH2_END; 234 235 /* Return the safe kernel mode buffer */ 236 *MappedSystemVa = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority); 237 if (*MappedSystemVa == NULL) 238 { 239 ExUnlockUserBuffer(Mdl); 240 return STATUS_INSUFFICIENT_RESOURCES; 241 } 242 243 /* Return the MDL */ 244 *OutMdl = Mdl; 245 return STATUS_SUCCESS; 246 } 247 248 NTSTATUS 249 NTAPI 250 ExpGetRawSMBiosTable( 251 _Out_opt_ PVOID Buffer, 252 _Out_ ULONG * OutSize, 253 _In_ ULONG BufferSize) 254 { 255 NTSTATUS Status; 256 PVOID DataBlockObject; 257 PWNODE_ALL_DATA AllData; 258 ULONG WMIBufSize; 259 260 ASSERT(OutSize != NULL); 261 *OutSize = 0; 262 263 /* Open the data block object for the SMBIOS table */ 264 Status = IoWMIOpenBlock(&MSSmBios_RawSMBiosTables_GUID, 265 WMIGUID_QUERY, 266 &DataBlockObject); 267 if (!NT_SUCCESS(Status)) 268 { 269 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status); 270 return Status; 271 } 272 273 /* Query the required buffer size */ 274 WMIBufSize = 0; 275 Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, NULL); 276 if (!NT_SUCCESS(Status)) 277 { 278 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status); 279 return Status; 280 } 281 282 AllData = ExAllocatePoolWithTag(PagedPool, WMIBufSize, 'itfS'); 283 if (AllData == NULL) 284 { 285 DPRINT1("Failed to allocate %lu bytes for SMBIOS tables\n", WMIBufSize); 286 return STATUS_INSUFFICIENT_RESOURCES; 287 } 288 289 /* Query the buffer data */ 290 Status = IoWMIQueryAllData(DataBlockObject, &WMIBufSize, AllData); 291 if (!NT_SUCCESS(Status)) 292 { 293 DPRINT1("IoWMIOpenBlock failed: 0x%08lx\n", Status); 294 ExFreePoolWithTag(AllData, 'itfS'); 295 return Status; 296 } 297 298 Status = STATUS_SUCCESS; 299 *OutSize = AllData->FixedInstanceSize; 300 if (Buffer != NULL) 301 { 302 if (BufferSize >= *OutSize) 303 { 304 RtlMoveMemory(Buffer, AllData + 1, *OutSize); 305 } 306 else 307 { 308 Status = STATUS_BUFFER_TOO_SMALL; 309 } 310 } 311 312 /* Free the buffer */ 313 ExFreePoolWithTag(AllData, 'itfS'); 314 return Status; 315 } 316 317 /* FUNCTIONS *****************************************************************/ 318 319 /* 320 * @implemented 321 */ 322 VOID 323 NTAPI 324 ExGetCurrentProcessorCpuUsage(PULONG CpuUsage) 325 { 326 PKPRCB Prcb; 327 ULONG TotalTime; 328 ULONGLONG ScaledIdle; 329 330 Prcb = KeGetCurrentPrcb(); 331 332 ScaledIdle = (ULONGLONG)Prcb->IdleThread->KernelTime * 100; 333 TotalTime = Prcb->KernelTime + Prcb->UserTime; 334 if (TotalTime != 0) 335 *CpuUsage = (ULONG)(100 - (ScaledIdle / TotalTime)); 336 else 337 *CpuUsage = 0; 338 } 339 340 /* 341 * @implemented 342 */ 343 VOID 344 NTAPI 345 ExGetCurrentProcessorCounts(PULONG IdleTime, 346 PULONG KernelAndUserTime, 347 PULONG ProcessorNumber) 348 { 349 PKPRCB Prcb; 350 351 Prcb = KeGetCurrentPrcb(); 352 353 *IdleTime = Prcb->IdleThread->KernelTime; 354 *KernelAndUserTime = Prcb->KernelTime + Prcb->UserTime; 355 *ProcessorNumber = (ULONG)Prcb->Number; 356 } 357 358 /* 359 * @implemented 360 */ 361 BOOLEAN 362 NTAPI 363 ExIsProcessorFeaturePresent(IN ULONG ProcessorFeature) 364 { 365 /* Quick check to see if it exists at all */ 366 if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return(FALSE); 367 368 /* Return our support for it */ 369 return(SharedUserData->ProcessorFeatures[ProcessorFeature]); 370 } 371 372 /* 373 * @implemented 374 */ 375 BOOLEAN 376 NTAPI 377 ExVerifySuite(SUITE_TYPE SuiteType) 378 { 379 if (SuiteType == Personal) return TRUE; 380 return FALSE; 381 } 382 383 NTSTATUS 384 NTAPI 385 NtQuerySystemEnvironmentValue(IN PUNICODE_STRING VariableName, 386 OUT PWSTR ValueBuffer, 387 IN ULONG ValueBufferLength, 388 IN OUT PULONG ReturnLength OPTIONAL) 389 { 390 ANSI_STRING AName; 391 UNICODE_STRING WName; 392 ARC_STATUS Result; 393 PCH AnsiValueBuffer; 394 ANSI_STRING AValue; 395 UNICODE_STRING WValue; 396 KPROCESSOR_MODE PreviousMode; 397 NTSTATUS Status; 398 PAGED_CODE(); 399 400 /* Check if the call came from user mode */ 401 PreviousMode = ExGetPreviousMode(); 402 if (PreviousMode != KernelMode) 403 { 404 _SEH2_TRY 405 { 406 /* Probe the input and output buffers */ 407 ProbeForRead(VariableName, sizeof(UNICODE_STRING), sizeof(ULONG)); 408 ProbeForWrite(ValueBuffer, ValueBufferLength, sizeof(WCHAR)); 409 if (ReturnLength != NULL) ProbeForWriteUlong(ReturnLength); 410 } 411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 412 { 413 /* Return the exception code */ 414 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 415 } 416 _SEH2_END; 417 } 418 419 /* According to NTInternals the SeSystemEnvironmentName privilege is required! */ 420 if (!SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, PreviousMode)) 421 { 422 DPRINT1("NtQuerySystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n"); 423 return STATUS_PRIVILEGE_NOT_HELD; 424 } 425 426 /* Copy the name to kernel space if necessary */ 427 Status = ProbeAndCaptureUnicodeString(&WName, PreviousMode, VariableName); 428 if (!NT_SUCCESS(Status)) return Status; 429 430 /* Convert the name to ANSI and release the captured UNICODE string */ 431 Status = RtlUnicodeStringToAnsiString(&AName, &WName, TRUE); 432 ReleaseCapturedUnicodeString(&WName, PreviousMode); 433 if (!NT_SUCCESS(Status)) return Status; 434 435 /* Allocate a buffer for the ANSI environment variable */ 436 AnsiValueBuffer = ExAllocatePoolWithTag(NonPagedPool, MAX_ENVVAL_SIZE, 'rvnE'); 437 if (AnsiValueBuffer == NULL) 438 { 439 RtlFreeAnsiString(&AName); 440 return STATUS_INSUFFICIENT_RESOURCES; 441 } 442 443 /* Get the environment variable and free the ANSI name */ 444 Result = HalGetEnvironmentVariable(AName.Buffer, 445 MAX_ENVVAL_SIZE, 446 AnsiValueBuffer); 447 RtlFreeAnsiString(&AName); 448 449 /* Check if we had success */ 450 if (Result == ESUCCESS) 451 { 452 /* Copy the result back to the caller. */ 453 _SEH2_TRY 454 { 455 /* Initialize ANSI string from the result */ 456 RtlInitAnsiString(&AValue, AnsiValueBuffer); 457 458 /* Initialize a UNICODE string from the callers buffer */ 459 RtlInitEmptyUnicodeString(&WValue, ValueBuffer, (USHORT)ValueBufferLength); 460 461 /* Convert the result to UNICODE */ 462 Status = RtlAnsiStringToUnicodeString(&WValue, &AValue, FALSE); 463 464 if (ReturnLength != NULL) 465 *ReturnLength = WValue.Length; 466 } 467 _SEH2_EXCEPT(ExSystemExceptionFilter()) 468 { 469 Status = _SEH2_GetExceptionCode(); 470 } 471 _SEH2_END; 472 } 473 else 474 { 475 Status = STATUS_UNSUCCESSFUL; 476 } 477 478 /* Free the allocated ANSI value buffer */ 479 ExFreePoolWithTag(AnsiValueBuffer, 'rvnE'); 480 481 return Status; 482 } 483 484 485 NTSTATUS 486 NTAPI 487 NtSetSystemEnvironmentValue(IN PUNICODE_STRING VariableName, 488 IN PUNICODE_STRING Value) 489 { 490 UNICODE_STRING CapturedName, CapturedValue; 491 ANSI_STRING AName, AValue; 492 KPROCESSOR_MODE PreviousMode; 493 NTSTATUS Status; 494 495 PAGED_CODE(); 496 497 PreviousMode = ExGetPreviousMode(); 498 499 /* 500 * Copy the strings to kernel space if necessary 501 */ 502 Status = ProbeAndCaptureUnicodeString(&CapturedName, 503 PreviousMode, 504 VariableName); 505 if (NT_SUCCESS(Status)) 506 { 507 Status = ProbeAndCaptureUnicodeString(&CapturedValue, 508 PreviousMode, 509 Value); 510 if (NT_SUCCESS(Status)) 511 { 512 /* 513 * according to ntinternals the SeSystemEnvironmentName privilege is required! 514 */ 515 if (SeSinglePrivilegeCheck(SeSystemEnvironmentPrivilege, 516 PreviousMode)) 517 { 518 /* 519 * convert the strings to ANSI 520 */ 521 Status = RtlUnicodeStringToAnsiString(&AName, 522 &CapturedName, 523 TRUE); 524 if (NT_SUCCESS(Status)) 525 { 526 Status = RtlUnicodeStringToAnsiString(&AValue, 527 &CapturedValue, 528 TRUE); 529 if (NT_SUCCESS(Status)) 530 { 531 ARC_STATUS Result = HalSetEnvironmentVariable(AName.Buffer, 532 AValue.Buffer); 533 534 Status = (Result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL); 535 } 536 } 537 } 538 else 539 { 540 DPRINT1("NtSetSystemEnvironmentValue: Caller requires the SeSystemEnvironmentPrivilege privilege!\n"); 541 Status = STATUS_PRIVILEGE_NOT_HELD; 542 } 543 544 ReleaseCapturedUnicodeString(&CapturedValue, 545 PreviousMode); 546 } 547 548 ReleaseCapturedUnicodeString(&CapturedName, 549 PreviousMode); 550 } 551 552 return Status; 553 } 554 555 NTSTATUS 556 NTAPI 557 NtEnumerateSystemEnvironmentValuesEx(IN ULONG InformationClass, 558 IN PVOID Buffer, 559 IN ULONG BufferLength) 560 { 561 UNIMPLEMENTED; 562 return STATUS_NOT_IMPLEMENTED; 563 } 564 565 NTSTATUS 566 NTAPI 567 NtQuerySystemEnvironmentValueEx( 568 _In_ PUNICODE_STRING VariableName, 569 _In_ LPGUID VendorGuid, 570 _Out_opt_ PVOID Value, 571 _Inout_ PULONG ReturnLength, 572 _Out_opt_ PULONG Attributes) 573 { 574 UNIMPLEMENTED; 575 return STATUS_NOT_IMPLEMENTED; 576 } 577 578 NTSTATUS 579 NTAPI 580 NtSetSystemEnvironmentValueEx( 581 _In_ PUNICODE_STRING VariableName, 582 _In_ LPGUID VendorGuid, 583 _In_reads_bytes_opt_(ValueLength) PVOID Value, 584 _In_ ULONG ValueLength, 585 _In_ ULONG Attributes) 586 { 587 UNIMPLEMENTED; 588 return STATUS_NOT_IMPLEMENTED; 589 } 590 591 /* --- Query/Set System Information --- */ 592 593 /* 594 * NOTE: QSI_DEF(n) and SSI_DEF(n) define _cdecl function symbols 595 * so the stack is popped only in one place on x86 platform. 596 */ 597 #define QSI_USE(n) QSI##n 598 #define QSI_DEF(n) \ 599 static NTSTATUS QSI_USE(n) (PVOID Buffer, ULONG Size, PULONG ReqSize) 600 601 #define SSI_USE(n) SSI##n 602 #define SSI_DEF(n) \ 603 static NTSTATUS SSI_USE(n) (PVOID Buffer, ULONG Size) 604 605 VOID 606 NTAPI 607 ExQueryPoolUsage(OUT PULONG PagedPoolPages, 608 OUT PULONG NonPagedPoolPages, 609 OUT PULONG PagedPoolAllocs, 610 OUT PULONG PagedPoolFrees, 611 OUT PULONG PagedPoolLookasideHits, 612 OUT PULONG NonPagedPoolAllocs, 613 OUT PULONG NonPagedPoolFrees, 614 OUT PULONG NonPagedPoolLookasideHits); 615 616 /* Class 0 - Basic Information */ 617 QSI_DEF(SystemBasicInformation) 618 { 619 PSYSTEM_BASIC_INFORMATION Sbi 620 = (PSYSTEM_BASIC_INFORMATION) Buffer; 621 622 *ReqSize = sizeof(SYSTEM_BASIC_INFORMATION); 623 624 /* Check user buffer's size */ 625 if (Size != sizeof(SYSTEM_BASIC_INFORMATION)) 626 { 627 return STATUS_INFO_LENGTH_MISMATCH; 628 } 629 630 RtlZeroMemory(Sbi, Size); 631 Sbi->Reserved = 0; 632 Sbi->TimerResolution = KeMaximumIncrement; 633 Sbi->PageSize = PAGE_SIZE; 634 Sbi->NumberOfPhysicalPages = MmNumberOfPhysicalPages; 635 Sbi->LowestPhysicalPageNumber = (ULONG)MmLowestPhysicalPage; 636 Sbi->HighestPhysicalPageNumber = (ULONG)MmHighestPhysicalPage; 637 Sbi->AllocationGranularity = MM_VIRTMEM_GRANULARITY; /* hard coded on Intel? */ 638 Sbi->MinimumUserModeAddress = 0x10000; /* Top of 64k */ 639 Sbi->MaximumUserModeAddress = (ULONG_PTR)MmHighestUserAddress; 640 Sbi->ActiveProcessorsAffinityMask = KeActiveProcessors; 641 Sbi->NumberOfProcessors = KeNumberProcessors; 642 643 return STATUS_SUCCESS; 644 } 645 646 /* Class 1 - Processor Information */ 647 QSI_DEF(SystemProcessorInformation) 648 { 649 PSYSTEM_PROCESSOR_INFORMATION Spi 650 = (PSYSTEM_PROCESSOR_INFORMATION) Buffer; 651 652 *ReqSize = sizeof(SYSTEM_PROCESSOR_INFORMATION); 653 654 /* Check user buffer's size */ 655 if (Size < sizeof(SYSTEM_PROCESSOR_INFORMATION)) 656 { 657 return STATUS_INFO_LENGTH_MISMATCH; 658 } 659 Spi->ProcessorArchitecture = KeProcessorArchitecture; 660 Spi->ProcessorLevel = KeProcessorLevel; 661 Spi->ProcessorRevision = KeProcessorRevision; 662 #if (NTDDI_VERSION < NTDDI_WIN8) 663 Spi->Reserved = 0; 664 #else 665 Spi->MaximumProcessors = 0; 666 #endif 667 668 /* According to Geoff Chappell, on Win 8.1 x64 / Win 10 x86, where this 669 field is extended to 64 bits, it continues to produce only the low 32 670 bits. For the full value, use SYSTEM_PROCESSOR_FEATURES_INFORMATION. 671 See https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/sysinfo/processor.htm 672 */ 673 Spi->ProcessorFeatureBits = (ULONG)KeFeatureBits; 674 675 DPRINT("Arch %u Level %u Rev 0x%x\n", Spi->ProcessorArchitecture, 676 Spi->ProcessorLevel, Spi->ProcessorRevision); 677 678 return STATUS_SUCCESS; 679 } 680 681 /* Class 2 - Performance Information */ 682 QSI_DEF(SystemPerformanceInformation) 683 { 684 LONG i; 685 ULONG IdleUser, IdleKernel; 686 PKPRCB Prcb; 687 PSYSTEM_PERFORMANCE_INFORMATION Spi 688 = (PSYSTEM_PERFORMANCE_INFORMATION) Buffer; 689 690 PEPROCESS TheIdleProcess; 691 692 *ReqSize = sizeof(SYSTEM_PERFORMANCE_INFORMATION); 693 694 /* Check user buffer's size */ 695 if (Size < sizeof(SYSTEM_PERFORMANCE_INFORMATION)) 696 { 697 return STATUS_INFO_LENGTH_MISMATCH; 698 } 699 700 TheIdleProcess = PsIdleProcess; 701 702 IdleKernel = KeQueryRuntimeProcess(&TheIdleProcess->Pcb, &IdleUser); 703 Spi->IdleProcessTime.QuadPart = UInt32x32To64(IdleKernel, KeMaximumIncrement); 704 Spi->IoReadTransferCount = IoReadTransferCount; 705 Spi->IoWriteTransferCount = IoWriteTransferCount; 706 Spi->IoOtherTransferCount = IoOtherTransferCount; 707 Spi->IoReadOperationCount = IoReadOperationCount; 708 Spi->IoWriteOperationCount = IoWriteOperationCount; 709 Spi->IoOtherOperationCount = IoOtherOperationCount; 710 for (i = 0; i < KeNumberProcessors; i ++) 711 { 712 Prcb = KiProcessorBlock[i]; 713 if (Prcb) 714 { 715 Spi->IoReadTransferCount.QuadPart += Prcb->IoReadTransferCount.QuadPart; 716 Spi->IoWriteTransferCount.QuadPart += Prcb->IoWriteTransferCount.QuadPart; 717 Spi->IoOtherTransferCount.QuadPart += Prcb->IoOtherTransferCount.QuadPart; 718 Spi->IoReadOperationCount += Prcb->IoReadOperationCount; 719 Spi->IoWriteOperationCount += Prcb->IoWriteOperationCount; 720 Spi->IoOtherOperationCount += Prcb->IoOtherOperationCount; 721 } 722 } 723 724 Spi->AvailablePages = (ULONG)MmAvailablePages; 725 726 Spi->CommittedPages = MmTotalCommittedPages; 727 /* 728 * Add up the full system total + pagefile. 729 * All this make Taskmgr happy but not sure it is the right numbers. 730 * This too, fixes some of GlobalMemoryStatusEx numbers. 731 */ 732 Spi->CommitLimit = MmNumberOfPhysicalPages + MiFreeSwapPages + MiUsedSwapPages; 733 734 Spi->PeakCommitment = MmPeakCommitment; 735 Spi->PageFaultCount = 0; /* FIXME */ 736 Spi->CopyOnWriteCount = 0; /* FIXME */ 737 Spi->TransitionCount = 0; /* FIXME */ 738 Spi->CacheTransitionCount = 0; /* FIXME */ 739 Spi->DemandZeroCount = 0; /* FIXME */ 740 Spi->PageReadCount = 0; /* FIXME */ 741 Spi->PageReadIoCount = 0; /* FIXME */ 742 Spi->CacheReadCount = 0; /* FIXME */ 743 Spi->CacheIoCount = 0; /* FIXME */ 744 Spi->DirtyPagesWriteCount = 0; /* FIXME */ 745 Spi->DirtyWriteIoCount = 0; /* FIXME */ 746 Spi->MappedPagesWriteCount = 0; /* FIXME */ 747 Spi->MappedWriteIoCount = 0; /* FIXME */ 748 749 Spi->PagedPoolPages = 0; 750 Spi->NonPagedPoolPages = 0; 751 Spi->PagedPoolAllocs = 0; 752 Spi->PagedPoolFrees = 0; 753 Spi->PagedPoolLookasideHits = 0; 754 Spi->NonPagedPoolAllocs = 0; 755 Spi->NonPagedPoolFrees = 0; 756 Spi->NonPagedPoolLookasideHits = 0; 757 ExQueryPoolUsage(&Spi->PagedPoolPages, 758 &Spi->NonPagedPoolPages, 759 &Spi->PagedPoolAllocs, 760 &Spi->PagedPoolFrees, 761 &Spi->PagedPoolLookasideHits, 762 &Spi->NonPagedPoolAllocs, 763 &Spi->NonPagedPoolFrees, 764 &Spi->NonPagedPoolLookasideHits); 765 Spi->FreeSystemPtes = 0; /* FIXME */ 766 767 Spi->ResidentSystemCodePage = 0; /* FIXME */ 768 769 Spi->TotalSystemDriverPages = 0; /* FIXME */ 770 Spi->Spare3Count = 0; /* FIXME */ 771 772 Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */ 773 Spi->ResidentPagedPoolPage = 0; /* FIXME */ 774 775 Spi->ResidentSystemDriverPage = 0; /* FIXME */ 776 Spi->CcFastReadNoWait = 0; /* FIXME */ 777 Spi->CcFastReadWait = 0; /* FIXME */ 778 Spi->CcFastReadResourceMiss = 0; /* FIXME */ 779 Spi->CcFastReadNotPossible = 0; /* FIXME */ 780 781 Spi->CcFastMdlReadNoWait = 0; /* FIXME */ 782 Spi->CcFastMdlReadWait = 0; /* FIXME */ 783 Spi->CcFastMdlReadResourceMiss = 0; /* FIXME */ 784 Spi->CcFastMdlReadNotPossible = 0; /* FIXME */ 785 786 Spi->CcMapDataNoWait = CcMapDataNoWait; 787 Spi->CcMapDataWait = CcMapDataWait; 788 Spi->CcMapDataNoWaitMiss = 0; /* FIXME */ 789 Spi->CcMapDataWaitMiss = 0; /* FIXME */ 790 791 Spi->CcPinMappedDataCount = CcPinMappedDataCount; 792 Spi->CcPinReadNoWait = CcPinReadNoWait; 793 Spi->CcPinReadWait = CcPinReadWait; 794 Spi->CcPinReadNoWaitMiss = 0; /* FIXME */ 795 Spi->CcPinReadWaitMiss = 0; /* FIXME */ 796 Spi->CcCopyReadNoWait = 0; /* FIXME */ 797 Spi->CcCopyReadWait = 0; /* FIXME */ 798 Spi->CcCopyReadNoWaitMiss = 0; /* FIXME */ 799 Spi->CcCopyReadWaitMiss = 0; /* FIXME */ 800 801 Spi->CcMdlReadNoWait = 0; /* FIXME */ 802 Spi->CcMdlReadWait = 0; /* FIXME */ 803 Spi->CcMdlReadNoWaitMiss = 0; /* FIXME */ 804 Spi->CcMdlReadWaitMiss = 0; /* FIXME */ 805 Spi->CcReadAheadIos = 0; /* FIXME */ 806 Spi->CcLazyWriteIos = CcLazyWriteIos; 807 Spi->CcLazyWritePages = CcLazyWritePages; 808 Spi->CcDataFlushes = CcDataFlushes; 809 Spi->CcDataPages = CcDataPages; 810 811 Spi->ContextSwitches = 0; 812 Spi->FirstLevelTbFills = 0; 813 Spi->SecondLevelTbFills = 0; 814 Spi->SystemCalls = 0; 815 for (i = 0; i < KeNumberProcessors; i ++) 816 { 817 Prcb = KiProcessorBlock[i]; 818 if (Prcb) 819 { 820 Spi->ContextSwitches += KeGetContextSwitches(Prcb); 821 Spi->FirstLevelTbFills += Prcb->KeFirstLevelTbFills; 822 Spi->SecondLevelTbFills += Prcb->KeSecondLevelTbFills; 823 Spi->SystemCalls += Prcb->KeSystemCalls; 824 } 825 } 826 827 return STATUS_SUCCESS; 828 } 829 830 /* Class 3 - Time Of Day Information */ 831 QSI_DEF(SystemTimeOfDayInformation) 832 { 833 SYSTEM_TIMEOFDAY_INFORMATION Sti; 834 LARGE_INTEGER CurrentTime; 835 836 /* Set amount of written information to 0 */ 837 *ReqSize = 0; 838 839 /* Check user buffer's size */ 840 if (Size > sizeof(SYSTEM_TIMEOFDAY_INFORMATION)) 841 { 842 return STATUS_INFO_LENGTH_MISMATCH; 843 } 844 845 /* Get current time */ 846 KeQuerySystemTime(&CurrentTime); 847 848 /* Zero local buffer */ 849 RtlZeroMemory(&Sti, sizeof(SYSTEM_TIMEOFDAY_INFORMATION)); 850 851 /* Fill local time structure */ 852 Sti.BootTime= KeBootTime; 853 Sti.CurrentTime = CurrentTime; 854 Sti.TimeZoneBias.QuadPart = ExpTimeZoneBias.QuadPart; 855 Sti.TimeZoneId = ExpTimeZoneId; 856 Sti.Reserved = 0; 857 858 /* Copy as much as requested by caller */ 859 RtlCopyMemory(Buffer, &Sti, Size); 860 861 /* Set amount of information we copied */ 862 *ReqSize = Size; 863 864 return STATUS_SUCCESS; 865 } 866 867 /* Class 4 - Path Information (DEPRECATED) */ 868 QSI_DEF(SystemPathInformation) 869 { 870 /* 871 * Since NT 3.51, this information class is trivially implemented. 872 * The path to the NT directory is now stored in KUSER_SHARED_DATA 873 * as the NtSystemRoot member. 874 * Windows Checked builds show the following message and break to 875 * the debugger before failing the function as not implemented. 876 */ 877 #if DBG 878 DPRINT1("EX: SystemPathInformation now available via SharedUserData\n"); 879 // DbgBreakPoint(); // Not needed in ReactOS. 880 #endif 881 return STATUS_NOT_IMPLEMENTED; 882 } 883 884 /* Class 5 - Process Information */ 885 QSI_DEF(SystemProcessInformation) 886 { 887 PSYSTEM_PROCESS_INFORMATION SpiCurrent; 888 PSYSTEM_THREAD_INFORMATION ThreadInfo; 889 PEPROCESS Process = NULL, SystemProcess; 890 PETHREAD CurrentThread; 891 ANSI_STRING ImageName; 892 ULONG CurrentSize; 893 USHORT ImageNameMaximumLength; // image name length in bytes 894 USHORT ImageNameLength; 895 PLIST_ENTRY CurrentEntry; 896 ULONG TotalSize = 0, ThreadsCount; 897 ULONG TotalUser, TotalKernel; 898 PUCHAR Current; 899 NTSTATUS Status = STATUS_SUCCESS; 900 PUNICODE_STRING TempProcessImageName; 901 _SEH2_VOLATILE PUNICODE_STRING ProcessImageName = NULL; 902 PWCHAR szSrc; 903 BOOLEAN Overflow = FALSE; 904 905 _SEH2_TRY 906 { 907 /* scan the process list */ 908 909 PSYSTEM_PROCESS_INFORMATION Spi 910 = (PSYSTEM_PROCESS_INFORMATION) Buffer; 911 912 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION); 913 914 /* Check for overflow */ 915 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION)) 916 { 917 Overflow = TRUE; 918 } 919 920 /* Zero user's buffer */ 921 if (!Overflow) RtlZeroMemory(Spi, Size); 922 923 SystemProcess = PsIdleProcess; 924 Process = SystemProcess; 925 Current = (PUCHAR) Spi; 926 927 do 928 { 929 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current; 930 931 /* Lock the Process */ 932 KeEnterCriticalRegion(); 933 ExAcquirePushLockShared(&Process->ProcessLock); 934 935 if ((Process->ProcessExiting) && 936 (Process->Pcb.Header.SignalState) && 937 !(Process->ActiveThreads) && 938 (IsListEmpty(&Process->Pcb.ThreadListHead))) 939 { 940 DPRINT1("Process %p (%s:%p) is a zombie\n", 941 Process, Process->ImageFileName, Process->UniqueProcessId); 942 CurrentSize = 0; 943 ImageNameMaximumLength = 0; 944 945 /* Unlock the Process */ 946 ExReleasePushLockShared(&Process->ProcessLock); 947 KeLeaveCriticalRegion(); 948 goto Skip; 949 } 950 951 ThreadsCount = 0; 952 CurrentEntry = Process->Pcb.ThreadListHead.Flink; 953 while (CurrentEntry != &Process->Pcb.ThreadListHead) 954 { 955 ThreadsCount++; 956 CurrentEntry = CurrentEntry->Flink; 957 } 958 959 // size of the structure for every process 960 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount; 961 ImageNameLength = 0; 962 Status = SeLocateProcessImageName(Process, &TempProcessImageName); 963 ProcessImageName = TempProcessImageName; 964 szSrc = NULL; 965 if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0)) 966 { 967 szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length); 968 /* Loop the file name*/ 969 while (szSrc > ProcessImageName->Buffer) 970 { 971 /* Make sure this isn't a backslash */ 972 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR) 973 { 974 szSrc++; 975 break; 976 } 977 else 978 { 979 ImageNameLength += sizeof(WCHAR); 980 } 981 } 982 } 983 if (!ImageNameLength && Process != PsIdleProcess) 984 { 985 ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR); 986 } 987 988 /* Round up the image name length as NT does */ 989 if (ImageNameLength > 0) 990 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8); 991 else 992 ImageNameMaximumLength = 0; 993 994 TotalSize += CurrentSize + ImageNameMaximumLength; 995 996 /* Check for overflow */ 997 if (TotalSize > Size) 998 { 999 Overflow = TRUE; 1000 } 1001 1002 /* Fill system information */ 1003 if (!Overflow) 1004 { 1005 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginning of the next structure 1006 SpiCurrent->NumberOfThreads = ThreadsCount; 1007 SpiCurrent->CreateTime = Process->CreateTime; 1008 SpiCurrent->ImageName.Length = ImageNameLength; 1009 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength; 1010 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize); 1011 1012 /* Copy name to the end of the struct */ 1013 if(Process != PsIdleProcess) 1014 { 1015 if (szSrc) 1016 { 1017 RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length); 1018 } 1019 else 1020 { 1021 RtlInitAnsiString(&ImageName, Process->ImageFileName); 1022 Status = RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE); 1023 if (!NT_SUCCESS(Status)) 1024 { 1025 SpiCurrent->ImageName.Length = 0; 1026 } 1027 } 1028 } 1029 else 1030 { 1031 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL); 1032 } 1033 1034 SpiCurrent->BasePriority = Process->Pcb.BasePriority; 1035 SpiCurrent->UniqueProcessId = Process->UniqueProcessId; 1036 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId; 1037 1038 /* PsIdleProcess shares its handle table with PsInitialSystemProcess, 1039 * so return the handle count for System only, not Idle one. */ 1040 SpiCurrent->HandleCount = (Process == PsIdleProcess) ? 0 : ObGetProcessHandleCount(Process); 1041 1042 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize; 1043 SpiCurrent->VirtualSize = Process->VirtualSize; 1044 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount; 1045 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize; 1046 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize; 1047 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[PsPagedPool]; 1048 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool]; 1049 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[PsNonPagedPool]; 1050 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[PsNonPagedPool]; 1051 SpiCurrent->PagefileUsage = Process->QuotaUsage[PsPageFile]; 1052 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[PsPageFile]; 1053 SpiCurrent->PrivatePageCount = Process->CommitCharge; 1054 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1); 1055 1056 CurrentEntry = Process->Pcb.ThreadListHead.Flink; 1057 while (CurrentEntry != &Process->Pcb.ThreadListHead) 1058 { 1059 CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, Tcb.ThreadListEntry); 1060 1061 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement); 1062 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement); 1063 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart; 1064 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime; 1065 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress; 1066 ThreadInfo->ClientId = CurrentThread->Cid; 1067 ThreadInfo->Priority = CurrentThread->Tcb.Priority; 1068 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority; 1069 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches; 1070 ThreadInfo->ThreadState = CurrentThread->Tcb.State; 1071 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason; 1072 1073 ThreadInfo++; 1074 CurrentEntry = CurrentEntry->Flink; 1075 } 1076 1077 /* Query total user/kernel times of a process */ 1078 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser); 1079 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement); 1080 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement); 1081 } 1082 1083 if (ProcessImageName) 1084 { 1085 /* Release the memory allocated by SeLocateProcessImageName */ 1086 ExFreePoolWithTag(ProcessImageName, TAG_SEPA); 1087 ProcessImageName = NULL; 1088 } 1089 1090 /* Unlock the Process */ 1091 ExReleasePushLockShared(&Process->ProcessLock); 1092 KeLeaveCriticalRegion(); 1093 1094 /* Handle idle process entry */ 1095 Skip: 1096 if (Process == PsIdleProcess) Process = NULL; 1097 1098 Process = PsGetNextProcess(Process); 1099 ThreadsCount = 0; 1100 if ((Process == SystemProcess) || (Process == NULL)) 1101 { 1102 if (!Overflow) 1103 SpiCurrent->NextEntryOffset = 0; 1104 break; 1105 } 1106 else 1107 Current += CurrentSize + ImageNameMaximumLength; 1108 } while ((Process != SystemProcess) && (Process != NULL)); 1109 1110 if(Process != NULL) 1111 ObDereferenceObject(Process); 1112 Status = STATUS_SUCCESS; 1113 } 1114 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1115 { 1116 if(Process != NULL) 1117 ObDereferenceObject(Process); 1118 if (ProcessImageName) 1119 { 1120 /* Release the memory allocated by SeLocateProcessImageName */ 1121 ExFreePoolWithTag(ProcessImageName, TAG_SEPA); 1122 } 1123 1124 Status = _SEH2_GetExceptionCode(); 1125 } 1126 _SEH2_END 1127 1128 if (Overflow) 1129 Status = STATUS_INFO_LENGTH_MISMATCH; 1130 1131 *ReqSize = TotalSize; 1132 return Status; 1133 } 1134 1135 /* Class 6 - Call Count Information */ 1136 QSI_DEF(SystemCallCountInformation) 1137 { 1138 /* FIXME */ 1139 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n"); 1140 return STATUS_NOT_IMPLEMENTED; 1141 } 1142 1143 /* Class 7 - Device Information */ 1144 QSI_DEF(SystemDeviceInformation) 1145 { 1146 PSYSTEM_DEVICE_INFORMATION Sdi 1147 = (PSYSTEM_DEVICE_INFORMATION) Buffer; 1148 PCONFIGURATION_INFORMATION ConfigInfo; 1149 1150 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION); 1151 1152 /* Check user buffer's size */ 1153 if (Size < sizeof(SYSTEM_DEVICE_INFORMATION)) 1154 { 1155 return STATUS_INFO_LENGTH_MISMATCH; 1156 } 1157 1158 ConfigInfo = IoGetConfigurationInformation(); 1159 1160 Sdi->NumberOfDisks = ConfigInfo->DiskCount; 1161 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount; 1162 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount; 1163 Sdi->NumberOfTapes = ConfigInfo->TapeCount; 1164 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount; 1165 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount; 1166 1167 return STATUS_SUCCESS; 1168 } 1169 1170 /* Class 8 - Processor Performance Information */ 1171 QSI_DEF(SystemProcessorPerformanceInformation) 1172 { 1173 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi 1174 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer; 1175 1176 LONG i; 1177 ULONG TotalTime; 1178 PKPRCB Prcb; 1179 1180 *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); 1181 1182 /* Check user buffer's size */ 1183 if (Size < *ReqSize) 1184 { 1185 return STATUS_INFO_LENGTH_MISMATCH; 1186 } 1187 1188 for (i = 0; i < KeNumberProcessors; i++) 1189 { 1190 /* Get the PRCB on this processor */ 1191 Prcb = KiProcessorBlock[i]; 1192 1193 /* Calculate total user and kernel times */ 1194 TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime; 1195 Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement); 1196 Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement); 1197 Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement); 1198 Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement); 1199 Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement); 1200 Spi->InterruptCount = Prcb->InterruptCount; 1201 Spi++; 1202 } 1203 1204 return STATUS_SUCCESS; 1205 } 1206 1207 /* Class 9 - Flags Information */ 1208 QSI_DEF(SystemFlagsInformation) 1209 { 1210 #if (NTDDI_VERSION >= NTDDI_VISTA) 1211 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION); 1212 #endif 1213 1214 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size) 1215 { 1216 return STATUS_INFO_LENGTH_MISMATCH; 1217 } 1218 1219 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag; 1220 #if (NTDDI_VERSION < NTDDI_VISTA) 1221 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION); 1222 #endif 1223 1224 return STATUS_SUCCESS; 1225 } 1226 1227 SSI_DEF(SystemFlagsInformation) 1228 { 1229 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size) 1230 { 1231 return STATUS_INFO_LENGTH_MISMATCH; 1232 } 1233 1234 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode())) 1235 { 1236 #if (NTDDI_VERSION < NTDDI_WIN7) 1237 return STATUS_ACCESS_VIOLATION; 1238 #else 1239 return STATUS_ACCESS_DENIED; 1240 #endif 1241 } 1242 1243 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags; 1244 return STATUS_SUCCESS; 1245 } 1246 1247 /* Class 10 - Call Time Information */ 1248 QSI_DEF(SystemCallTimeInformation) 1249 { 1250 /* FIXME */ 1251 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n"); 1252 return STATUS_NOT_IMPLEMENTED; 1253 } 1254 1255 /* Class 11 - Module Information */ 1256 QSI_DEF(SystemModuleInformation) 1257 { 1258 NTSTATUS Status; 1259 1260 /* Acquire system module list lock */ 1261 KeEnterCriticalRegion(); 1262 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE); 1263 1264 /* Call the generic handler with the system module list */ 1265 Status = ExpQueryModuleInformation(&PsLoadedModuleList, 1266 &MmLoadedUserImageList, 1267 (PRTL_PROCESS_MODULES)Buffer, 1268 Size, 1269 ReqSize); 1270 1271 /* Release list lock and return status */ 1272 ExReleaseResourceLite(&PsLoadedModuleResource); 1273 KeLeaveCriticalRegion(); 1274 return Status; 1275 } 1276 1277 /* Class 12 - Locks Information */ 1278 QSI_DEF(SystemLocksInformation) 1279 { 1280 /* FIXME */ 1281 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n"); 1282 return STATUS_NOT_IMPLEMENTED; 1283 } 1284 1285 /* Class 13 - Stack Trace Information */ 1286 QSI_DEF(SystemStackTraceInformation) 1287 { 1288 /* FIXME */ 1289 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n"); 1290 return STATUS_NOT_IMPLEMENTED; 1291 } 1292 1293 /* Class 14 - Paged Pool Information */ 1294 QSI_DEF(SystemPagedPoolInformation) 1295 { 1296 /* FIXME */ 1297 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n"); 1298 return STATUS_NOT_IMPLEMENTED; 1299 } 1300 1301 /* Class 15 - Non Paged Pool Information */ 1302 QSI_DEF(SystemNonPagedPoolInformation) 1303 { 1304 /* FIXME */ 1305 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n"); 1306 return STATUS_NOT_IMPLEMENTED; 1307 } 1308 1309 /* Class 16 - Handle Information */ 1310 QSI_DEF(SystemHandleInformation) 1311 { 1312 PSYSTEM_HANDLE_INFORMATION HandleInformation; 1313 PLIST_ENTRY NextTableEntry; 1314 PHANDLE_TABLE HandleTable; 1315 PHANDLE_TABLE_ENTRY HandleTableEntry; 1316 EXHANDLE Handle; 1317 ULONG Index = 0; 1318 NTSTATUS Status; 1319 PMDL Mdl; 1320 PAGED_CODE(); 1321 1322 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n"); 1323 1324 /* Set initial required buffer size */ 1325 *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handles); 1326 1327 /* Check user's buffer size */ 1328 if (Size < *ReqSize) 1329 { 1330 return STATUS_INFO_LENGTH_MISMATCH; 1331 } 1332 1333 /* We need to lock down the memory */ 1334 Status = ExLockUserBuffer(Buffer, 1335 Size, 1336 ExGetPreviousMode(), 1337 IoWriteAccess, 1338 (PVOID*)&HandleInformation, 1339 &Mdl); 1340 if (!NT_SUCCESS(Status)) 1341 { 1342 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status); 1343 return Status; 1344 } 1345 1346 /* Reset of count of handles */ 1347 HandleInformation->NumberOfHandles = 0; 1348 1349 /* Enter a critical region */ 1350 KeEnterCriticalRegion(); 1351 1352 /* Acquire the handle table lock */ 1353 ExAcquirePushLockShared(&HandleTableListLock); 1354 1355 /* Enumerate all system handles */ 1356 for (NextTableEntry = HandleTableListHead.Flink; 1357 NextTableEntry != &HandleTableListHead; 1358 NextTableEntry = NextTableEntry->Flink) 1359 { 1360 /* Get current handle table */ 1361 HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList); 1362 1363 /* Set the initial value and loop the entries */ 1364 Handle.Value = 0; 1365 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) 1366 { 1367 /* Validate the entry */ 1368 if ((HandleTableEntry->Object) && 1369 (HandleTableEntry->NextFreeTableEntry != -2)) 1370 { 1371 /* Increase of count of handles */ 1372 ++HandleInformation->NumberOfHandles; 1373 1374 /* Lock the entry */ 1375 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1376 { 1377 /* Increase required buffer size */ 1378 *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO); 1379 1380 /* Check user's buffer size */ 1381 if (*ReqSize > Size) 1382 { 1383 Status = STATUS_INFO_LENGTH_MISMATCH; 1384 } 1385 else 1386 { 1387 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); 1388 1389 /* Filling handle information */ 1390 HandleInformation->Handles[Index].UniqueProcessId = 1391 (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId; 1392 1393 HandleInformation->Handles[Index].CreatorBackTraceIndex = 0; 1394 1395 #if 0 /* FIXME!!! Type field corrupted */ 1396 HandleInformation->Handles[Index].ObjectTypeIndex = 1397 (UCHAR) ObjectHeader->Type->Index; 1398 #else 1399 HandleInformation->Handles[Index].ObjectTypeIndex = 0; 1400 #endif 1401 1402 HandleInformation->Handles[Index].HandleAttributes = 1403 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 1404 1405 HandleInformation->Handles[Index].HandleValue = 1406 (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay; 1407 1408 HandleInformation->Handles[Index].Object = &ObjectHeader->Body; 1409 1410 HandleInformation->Handles[Index].GrantedAccess = 1411 HandleTableEntry->GrantedAccess; 1412 1413 ++Index; 1414 } 1415 1416 /* Unlock it */ 1417 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); 1418 } 1419 } 1420 1421 /* Go to the next entry */ 1422 Handle.Value += sizeof(HANDLE); 1423 } 1424 } 1425 1426 /* Release the lock */ 1427 ExReleasePushLockShared(&HandleTableListLock); 1428 1429 /* Leave the critical region */ 1430 KeLeaveCriticalRegion(); 1431 1432 /* Release the locked user buffer */ 1433 ExUnlockUserBuffer(Mdl); 1434 1435 return Status; 1436 } 1437 1438 /* Class 17 - Information */ 1439 QSI_DEF(SystemObjectInformation) 1440 { 1441 /* FIXME */ 1442 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n"); 1443 return STATUS_NOT_IMPLEMENTED; 1444 } 1445 1446 /* Class 18 - Information */ 1447 QSI_DEF(SystemPageFileInformation) 1448 { 1449 UNICODE_STRING FileName; /* FIXME */ 1450 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer; 1451 1452 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION)) 1453 { 1454 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION); 1455 return STATUS_INFO_LENGTH_MISMATCH; 1456 } 1457 1458 RtlInitUnicodeString(&FileName, NULL); /* FIXME */ 1459 1460 /* FIXME */ 1461 Spfi->NextEntryOffset = 0; 1462 1463 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages; 1464 Spfi->TotalInUse = MiUsedSwapPages; 1465 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */ 1466 Spfi->PageFileName = FileName; 1467 return STATUS_SUCCESS; 1468 } 1469 1470 /* Class 19 - Vdm Instemul Information */ 1471 QSI_DEF(SystemVdmInstemulInformation) 1472 { 1473 /* FIXME */ 1474 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n"); 1475 return STATUS_NOT_IMPLEMENTED; 1476 } 1477 1478 /* Class 20 - Vdm Bop Information */ 1479 QSI_DEF(SystemVdmBopInformation) 1480 { 1481 /* FIXME */ 1482 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n"); 1483 return STATUS_NOT_IMPLEMENTED; 1484 } 1485 1486 /* Class 21 - File Cache Information */ 1487 QSI_DEF(SystemFileCacheInformation) 1488 { 1489 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer; 1490 1491 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION); 1492 1493 if (Size < *ReqSize) 1494 { 1495 return STATUS_INFO_LENGTH_MISMATCH; 1496 } 1497 1498 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION)); 1499 1500 /* Return the Byte size not the page size. */ 1501 Sci->CurrentSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */ 1502 Sci->PeakSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */ 1503 /* Taskmgr multiplies this one by page size right away */ 1504 Sci->CurrentSizeIncludingTransitionInPages = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME: Should be */ 1505 /* system working set and standby pages. */ 1506 Sci->PageFaultCount = 0; /* FIXME */ 1507 Sci->MinimumWorkingSet = 0; /* FIXME */ 1508 Sci->MaximumWorkingSet = 0; /* FIXME */ 1509 1510 return STATUS_SUCCESS; 1511 } 1512 1513 SSI_DEF(SystemFileCacheInformation) 1514 { 1515 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION)) 1516 { 1517 return STATUS_INFO_LENGTH_MISMATCH; 1518 } 1519 /* FIXME */ 1520 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n"); 1521 return STATUS_NOT_IMPLEMENTED; 1522 } 1523 1524 /* Class 22 - Pool Tag Information */ 1525 QSI_DEF(SystemPoolTagInformation) 1526 { 1527 if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; 1528 return ExGetPoolTagInfo(Buffer, Size, ReqSize); 1529 } 1530 1531 /* Class 23 - Interrupt Information for all processors */ 1532 QSI_DEF(SystemInterruptInformation) 1533 { 1534 PKPRCB Prcb; 1535 LONG i; 1536 ULONG ti; 1537 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer; 1538 1539 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION)) 1540 { 1541 return STATUS_INFO_LENGTH_MISMATCH; 1542 } 1543 1544 ti = KeQueryTimeIncrement(); 1545 1546 for (i = 0; i < KeNumberProcessors; i++) 1547 { 1548 Prcb = KiProcessorBlock[i]; 1549 sii->ContextSwitches = KeGetContextSwitches(Prcb); 1550 sii->DpcCount = Prcb->DpcData[0].DpcCount; 1551 sii->DpcRate = Prcb->DpcRequestRate; 1552 sii->TimeIncrement = ti; 1553 sii->DpcBypassCount = 0; 1554 sii->ApcBypassCount = 0; 1555 sii++; 1556 } 1557 1558 return STATUS_SUCCESS; 1559 } 1560 1561 /* Class 24 - DPC Behaviour Information */ 1562 QSI_DEF(SystemDpcBehaviourInformation) 1563 { 1564 PSYSTEM_DPC_BEHAVIOR_INFORMATION sdbi = (PSYSTEM_DPC_BEHAVIOR_INFORMATION)Buffer; 1565 1566 if (Size < sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) 1567 { 1568 return STATUS_INFO_LENGTH_MISMATCH; 1569 } 1570 1571 sdbi->DpcQueueDepth = KiMaximumDpcQueueDepth; 1572 sdbi->MinimumDpcRate = KiMinimumDpcRate; 1573 sdbi->AdjustDpcThreshold = KiAdjustDpcThreshold; 1574 sdbi->IdealDpcRate = KiIdealDpcRate; 1575 1576 return STATUS_SUCCESS; 1577 } 1578 1579 SSI_DEF(SystemDpcBehaviourInformation) 1580 { 1581 /* FIXME */ 1582 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n"); 1583 return STATUS_NOT_IMPLEMENTED; 1584 } 1585 1586 /* Class 25 - Full Memory Information */ 1587 QSI_DEF(SystemFullMemoryInformation) 1588 { 1589 PULONG Spi = (PULONG) Buffer; 1590 1591 PEPROCESS TheIdleProcess; 1592 1593 *ReqSize = sizeof(ULONG); 1594 1595 if (sizeof(ULONG) != Size) 1596 { 1597 return STATUS_INFO_LENGTH_MISMATCH; 1598 } 1599 1600 DPRINT("SystemFullMemoryInformation\n"); 1601 1602 TheIdleProcess = PsIdleProcess; 1603 1604 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n", 1605 TheIdleProcess->UniqueProcessId, 1606 TheIdleProcess->Pcb.KernelTime, 1607 MiFreeSwapPages, 1608 MiUsedSwapPages); 1609 1610 *Spi = MiMemoryConsumers[MC_USER].PagesUsed; 1611 1612 return STATUS_SUCCESS; 1613 } 1614 1615 /* Class 26 - Load Image */ 1616 SSI_DEF(SystemLoadGdiDriverInformation) 1617 { 1618 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer; 1619 UNICODE_STRING ImageName; 1620 PVOID ImageBase; 1621 PVOID SectionPointer; 1622 ULONG_PTR EntryPoint; 1623 NTSTATUS Status; 1624 ULONG DirSize; 1625 PIMAGE_NT_HEADERS NtHeader; 1626 1627 /* Validate size */ 1628 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION)) 1629 { 1630 /* Incorrect buffer length, fail */ 1631 return STATUS_INFO_LENGTH_MISMATCH; 1632 } 1633 1634 /* Only kernel mode can call this function */ 1635 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD; 1636 1637 /* Load the driver */ 1638 ImageName = DriverInfo->DriverName; 1639 Status = MmLoadSystemImage(&ImageName, 1640 NULL, 1641 NULL, 1642 0, 1643 &SectionPointer, 1644 &ImageBase); 1645 if (!NT_SUCCESS(Status)) return Status; 1646 1647 /* Return the export pointer */ 1648 DriverInfo->ExportSectionPointer = 1649 RtlImageDirectoryEntryToData(ImageBase, 1650 TRUE, 1651 IMAGE_DIRECTORY_ENTRY_EXPORT, 1652 &DirSize); 1653 1654 /* Get the entrypoint */ 1655 NtHeader = RtlImageNtHeader(ImageBase); 1656 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; 1657 EntryPoint += (ULONG_PTR)ImageBase; 1658 1659 /* Save other data */ 1660 DriverInfo->ImageAddress = ImageBase; 1661 DriverInfo->SectionPointer = SectionPointer; 1662 DriverInfo->EntryPoint = (PVOID)EntryPoint; 1663 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage; 1664 1665 /* All is good */ 1666 return STATUS_SUCCESS; 1667 } 1668 1669 /* Class 27 - Unload Image */ 1670 SSI_DEF(SystemUnloadGdiDriverInformation) 1671 { 1672 PVOID *SectionPointer = Buffer; 1673 1674 /* Validate size */ 1675 if (Size != sizeof(PVOID)) 1676 { 1677 /* Incorrect length, fail */ 1678 return STATUS_INFO_LENGTH_MISMATCH; 1679 } 1680 1681 /* Only kernel mode can call this function */ 1682 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD; 1683 1684 /* Unload the image */ 1685 MmUnloadSystemImage(*SectionPointer); 1686 return STATUS_SUCCESS; 1687 } 1688 1689 /* Class 28 - Time Adjustment Information */ 1690 QSI_DEF(SystemTimeAdjustmentInformation) 1691 { 1692 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo = 1693 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer; 1694 1695 /* Check if enough storage was provided */ 1696 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size) 1697 { 1698 * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION); 1699 return STATUS_INFO_LENGTH_MISMATCH; 1700 } 1701 1702 /* Give time values to our caller */ 1703 TimeInfo->TimeIncrement = KeMaximumIncrement; 1704 TimeInfo->TimeAdjustment = KeTimeAdjustment; 1705 TimeInfo->Enable = !KiTimeAdjustmentEnabled; 1706 1707 return STATUS_SUCCESS; 1708 } 1709 1710 SSI_DEF(SystemTimeAdjustmentInformation) 1711 { 1712 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 1713 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo = 1714 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer; 1715 1716 /* Check size of a buffer, it must match our expectations */ 1717 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size) 1718 return STATUS_INFO_LENGTH_MISMATCH; 1719 1720 /* Check who is calling */ 1721 if (PreviousMode != KernelMode) 1722 { 1723 /* Check access rights */ 1724 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode)) 1725 { 1726 return STATUS_PRIVILEGE_NOT_HELD; 1727 } 1728 } 1729 1730 /* FIXME: behaviour suggests the member be named 'Disable' */ 1731 if (TimeInfo->Enable) 1732 { 1733 /* Disable time adjustment and set default value */ 1734 KiTimeAdjustmentEnabled = FALSE; 1735 KeTimeAdjustment = KeMaximumIncrement; 1736 } 1737 else 1738 { 1739 /* Check if a valid time adjustment value is given */ 1740 if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2; 1741 1742 /* Enable time adjustment and set the adjustment value */ 1743 KiTimeAdjustmentEnabled = TRUE; 1744 KeTimeAdjustment = TimeInfo->TimeAdjustment; 1745 } 1746 1747 return STATUS_SUCCESS; 1748 } 1749 1750 /* Class 29 - Summary Memory Information */ 1751 QSI_DEF(SystemSummaryMemoryInformation) 1752 { 1753 /* FIXME */ 1754 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n"); 1755 return STATUS_NOT_IMPLEMENTED; 1756 } 1757 1758 /* Class 30 - Next Event Id Information */ 1759 QSI_DEF(SystemNextEventIdInformation) 1760 { 1761 /* FIXME */ 1762 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n"); 1763 return STATUS_NOT_IMPLEMENTED; 1764 } 1765 1766 /* Class 31 */ 1767 QSI_DEF(SystemPerformanceTraceInformation) 1768 { 1769 /* FIXME */ 1770 DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n"); 1771 return STATUS_NOT_IMPLEMENTED; 1772 } 1773 1774 /* Class 32 - Crash Dump Information */ 1775 QSI_DEF(SystemCrashDumpInformation) 1776 { 1777 /* FIXME */ 1778 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n"); 1779 return STATUS_NOT_IMPLEMENTED; 1780 } 1781 1782 /* Class 33 - Exception Information */ 1783 QSI_DEF(SystemExceptionInformation) 1784 { 1785 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation = 1786 (PSYSTEM_EXCEPTION_INFORMATION)Buffer; 1787 PKPRCB Prcb; 1788 ULONG AlignmentFixupCount = 0, ExceptionDispatchCount = 0; 1789 ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0; 1790 CHAR i; 1791 1792 /* Check size of a buffer, it must match our expectations */ 1793 if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size) 1794 return STATUS_INFO_LENGTH_MISMATCH; 1795 1796 /* Sum up exception count information from all processors */ 1797 for (i = 0; i < KeNumberProcessors; i++) 1798 { 1799 Prcb = KiProcessorBlock[i]; 1800 if (Prcb) 1801 { 1802 AlignmentFixupCount += Prcb->KeAlignmentFixupCount; 1803 ExceptionDispatchCount += Prcb->KeExceptionDispatchCount; 1804 #ifndef _M_ARM 1805 FloatingEmulationCount += Prcb->KeFloatingEmulationCount; 1806 #endif // _M_ARM 1807 } 1808 } 1809 1810 /* Save information in user's buffer */ 1811 ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount; 1812 ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount; 1813 ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount; 1814 ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount; 1815 1816 return STATUS_SUCCESS; 1817 } 1818 1819 /* Class 34 - Crash Dump State Information */ 1820 QSI_DEF(SystemCrashDumpStateInformation) 1821 { 1822 /* FIXME */ 1823 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n"); 1824 return STATUS_NOT_IMPLEMENTED; 1825 } 1826 1827 /* Class 35 - Kernel Debugger Information */ 1828 QSI_DEF(SystemKernelDebuggerInformation) 1829 { 1830 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer; 1831 1832 #if (NTDDI_VERSION >= NTDDI_VISTA) 1833 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION); 1834 #endif 1835 1836 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION)) 1837 { 1838 return STATUS_INFO_LENGTH_MISMATCH; 1839 } 1840 1841 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED; 1842 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT; 1843 1844 #if (NTDDI_VERSION < NTDDI_VISTA) 1845 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION); 1846 #endif 1847 1848 return STATUS_SUCCESS; 1849 } 1850 1851 /* Class 36 - Context Switch Information */ 1852 QSI_DEF(SystemContextSwitchInformation) 1853 { 1854 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation = 1855 (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer; 1856 ULONG ContextSwitches; 1857 PKPRCB Prcb; 1858 CHAR i; 1859 1860 /* Check size of a buffer, it must match our expectations */ 1861 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size) 1862 return STATUS_INFO_LENGTH_MISMATCH; 1863 1864 /* Calculate total value of context switches across all processors */ 1865 ContextSwitches = 0; 1866 for (i = 0; i < KeNumberProcessors; i ++) 1867 { 1868 Prcb = KiProcessorBlock[i]; 1869 if (Prcb) 1870 { 1871 ContextSwitches += KeGetContextSwitches(Prcb); 1872 } 1873 } 1874 1875 ContextSwitchInformation->ContextSwitches = ContextSwitches; 1876 1877 /* FIXME */ 1878 ContextSwitchInformation->FindAny = 0; 1879 ContextSwitchInformation->FindLast = 0; 1880 ContextSwitchInformation->FindIdeal = 0; 1881 ContextSwitchInformation->IdleAny = 0; 1882 ContextSwitchInformation->IdleCurrent = 0; 1883 ContextSwitchInformation->IdleLast = 0; 1884 ContextSwitchInformation->IdleIdeal = 0; 1885 ContextSwitchInformation->PreemptAny = 0; 1886 ContextSwitchInformation->PreemptCurrent = 0; 1887 ContextSwitchInformation->PreemptLast = 0; 1888 ContextSwitchInformation->SwitchToIdle = 0; 1889 1890 return STATUS_SUCCESS; 1891 } 1892 1893 /* Class 37 - Registry Quota Information */ 1894 QSI_DEF(SystemRegistryQuotaInformation) 1895 { 1896 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer; 1897 1898 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION); 1899 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION)) 1900 { 1901 return STATUS_INFO_LENGTH_MISMATCH; 1902 } 1903 1904 DPRINT1("Faking max registry size of 32 MB\n"); 1905 srqi->RegistryQuotaAllowed = 0x2000000; 1906 srqi->RegistryQuotaUsed = 0x200000; 1907 srqi->PagedPoolSize = 0x200000; 1908 1909 return STATUS_SUCCESS; 1910 } 1911 1912 SSI_DEF(SystemRegistryQuotaInformation) 1913 { 1914 /* FIXME */ 1915 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n"); 1916 return STATUS_NOT_IMPLEMENTED; 1917 } 1918 1919 /* Class 38 - Load And Call Image */ 1920 SSI_DEF(SystemExtendServiceTableInformation) 1921 { 1922 UNICODE_STRING ImageName; 1923 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 1924 PLDR_DATA_TABLE_ENTRY ModuleObject; 1925 NTSTATUS Status; 1926 PIMAGE_NT_HEADERS NtHeader; 1927 DRIVER_OBJECT Win32k; 1928 PDRIVER_INITIALIZE DriverInit; 1929 PVOID ImageBase; 1930 ULONG_PTR EntryPoint; 1931 1932 /* Validate the size */ 1933 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH; 1934 1935 /* Check who is calling */ 1936 if (PreviousMode != KernelMode) 1937 { 1938 static const UNICODE_STRING Win32kName = 1939 RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\win32k.sys"); 1940 1941 /* Make sure we can load drivers */ 1942 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode)) 1943 { 1944 /* FIXME: We can't, fail */ 1945 return STATUS_PRIVILEGE_NOT_HELD; 1946 } 1947 1948 _SEH2_TRY 1949 { 1950 /* Probe and copy the unicode string */ 1951 ProbeForRead(Buffer, sizeof(ImageName), 1); 1952 ImageName = *(PUNICODE_STRING)Buffer; 1953 1954 /* Probe the string buffer */ 1955 ProbeForRead(ImageName.Buffer, ImageName.Length, sizeof(WCHAR)); 1956 1957 /* Check if we have the correct name (nothing else is allowed!) */ 1958 if (!RtlEqualUnicodeString(&ImageName, &Win32kName, FALSE)) 1959 { 1960 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD); 1961 } 1962 } 1963 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1964 { 1965 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 1966 } 1967 _SEH2_END; 1968 1969 /* Recursively call the function, so that we are from kernel mode */ 1970 return ZwSetSystemInformation(SystemExtendServiceTableInformation, 1971 (PVOID)&Win32kName, 1972 sizeof(Win32kName)); 1973 } 1974 1975 /* Load the image */ 1976 Status = MmLoadSystemImage((PUNICODE_STRING)Buffer, 1977 NULL, 1978 NULL, 1979 0, 1980 (PVOID)&ModuleObject, 1981 &ImageBase); 1982 1983 if (!NT_SUCCESS(Status)) return Status; 1984 1985 /* Get the headers */ 1986 NtHeader = RtlImageNtHeader(ImageBase); 1987 if (!NtHeader) 1988 { 1989 /* Fail */ 1990 MmUnloadSystemImage(ModuleObject); 1991 return STATUS_INVALID_IMAGE_FORMAT; 1992 } 1993 1994 /* Get the entrypoint */ 1995 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; 1996 EntryPoint += (ULONG_PTR)ImageBase; 1997 DriverInit = (PDRIVER_INITIALIZE)EntryPoint; 1998 1999 /* Create a dummy device */ 2000 RtlZeroMemory(&Win32k, sizeof(Win32k)); 2001 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 2002 Win32k.DriverStart = ImageBase; 2003 2004 /* Call it */ 2005 Status = (DriverInit)(&Win32k, NULL); 2006 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 2007 2008 /* Unload if we failed */ 2009 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject); 2010 return Status; 2011 } 2012 2013 /* Class 39 - Priority Separation */ 2014 SSI_DEF(SystemPrioritySeperation) 2015 { 2016 /* Check if the size is correct */ 2017 if (Size != sizeof(ULONG)) 2018 { 2019 return STATUS_INFO_LENGTH_MISMATCH; 2020 } 2021 2022 /* We need the TCB privilege */ 2023 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, ExGetPreviousMode())) 2024 { 2025 return STATUS_PRIVILEGE_NOT_HELD; 2026 } 2027 2028 /* Modify the quantum table */ 2029 PsChangeQuantumTable(TRUE, *(PULONG)Buffer); 2030 2031 return STATUS_SUCCESS; 2032 } 2033 2034 /* Class 40 */ 2035 QSI_DEF(SystemVerifierAddDriverInformation) 2036 { 2037 /* FIXME */ 2038 DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n"); 2039 return STATUS_NOT_IMPLEMENTED; 2040 } 2041 2042 /* Class 41 */ 2043 QSI_DEF(SystemVerifierRemoveDriverInformation) 2044 { 2045 /* FIXME */ 2046 DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n"); 2047 return STATUS_NOT_IMPLEMENTED; 2048 } 2049 2050 /* Class 42 - Power Information */ 2051 QSI_DEF(SystemProcessorIdleInformation) 2052 { 2053 *ReqSize = sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors; 2054 2055 if (sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors > Size) 2056 { 2057 return STATUS_INFO_LENGTH_MISMATCH; 2058 } 2059 2060 /* FIXME */ 2061 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n"); 2062 return STATUS_NOT_IMPLEMENTED; 2063 } 2064 2065 /* Class 43 */ 2066 QSI_DEF(SystemLegacyDriverInformation) 2067 { 2068 /* FIXME */ 2069 DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n"); 2070 return STATUS_NOT_IMPLEMENTED; 2071 } 2072 2073 /* Class 44 - Current Time Zone Information */ 2074 QSI_DEF(SystemCurrentTimeZoneInformation) 2075 { 2076 *ReqSize = sizeof(RTL_TIME_ZONE_INFORMATION); 2077 2078 if (sizeof(RTL_TIME_ZONE_INFORMATION) != Size) 2079 { 2080 return STATUS_INFO_LENGTH_MISMATCH; 2081 } 2082 2083 /* Copy the time zone information struct */ 2084 memcpy(Buffer, 2085 &ExpTimeZoneInfo, 2086 sizeof(RTL_TIME_ZONE_INFORMATION)); 2087 2088 return STATUS_SUCCESS; 2089 } 2090 2091 SSI_DEF(SystemCurrentTimeZoneInformation) 2092 { 2093 /* Check user buffer's size */ 2094 if (Size < sizeof(RTL_TIME_ZONE_INFORMATION)) 2095 { 2096 return STATUS_INFO_LENGTH_MISMATCH; 2097 } 2098 2099 return ExpSetTimeZoneInformation((PRTL_TIME_ZONE_INFORMATION)Buffer); 2100 } 2101 2102 static 2103 VOID 2104 ExpCopyLookasideInformation( 2105 PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer, 2106 PULONG RemainingPointer, 2107 PLIST_ENTRY ListHead, 2108 BOOLEAN ListUsesMisses) 2109 2110 { 2111 PSYSTEM_LOOKASIDE_INFORMATION Info; 2112 PGENERAL_LOOKASIDE LookasideList; 2113 PLIST_ENTRY ListEntry; 2114 ULONG Remaining; 2115 2116 /* Get info pointer and remaining count of free array element */ 2117 Info = *InfoPointer; 2118 Remaining = *RemainingPointer; 2119 2120 /* Loop as long as we have lookaside lists and free array elements */ 2121 for (ListEntry = ListHead->Flink; 2122 (ListEntry != ListHead) && (Remaining > 0); 2123 ListEntry = ListEntry->Flink, Remaining--) 2124 { 2125 LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry); 2126 2127 /* Fill the next array element */ 2128 Info->CurrentDepth = LookasideList->Depth; 2129 Info->MaximumDepth = LookasideList->MaximumDepth; 2130 Info->TotalAllocates = LookasideList->TotalAllocates; 2131 Info->TotalFrees = LookasideList->TotalFrees; 2132 Info->Type = LookasideList->Type; 2133 Info->Tag = LookasideList->Tag; 2134 Info->Size = LookasideList->Size; 2135 2136 /* Check how the lists track misses/hits */ 2137 if (ListUsesMisses) 2138 { 2139 /* Copy misses */ 2140 Info->AllocateMisses = LookasideList->AllocateMisses; 2141 Info->FreeMisses = LookasideList->FreeMisses; 2142 } 2143 else 2144 { 2145 /* Calculate misses */ 2146 Info->AllocateMisses = LookasideList->TotalAllocates 2147 - LookasideList->AllocateHits; 2148 Info->FreeMisses = LookasideList->TotalFrees 2149 - LookasideList->FreeHits; 2150 } 2151 } 2152 2153 /* Return the updated pointer and remaining count */ 2154 *InfoPointer = Info; 2155 *RemainingPointer = Remaining; 2156 } 2157 2158 /* Class 45 - Lookaside Information */ 2159 QSI_DEF(SystemLookasideInformation) 2160 { 2161 KPROCESSOR_MODE PreviousMode; 2162 PSYSTEM_LOOKASIDE_INFORMATION Info; 2163 PMDL Mdl; 2164 ULONG MaxCount, Remaining; 2165 KIRQL OldIrql; 2166 NTSTATUS Status; 2167 2168 /* First we need to lock down the memory, since we are going to access it 2169 at high IRQL */ 2170 PreviousMode = ExGetPreviousMode(); 2171 Status = ExLockUserBuffer(Buffer, 2172 Size, 2173 PreviousMode, 2174 IoWriteAccess, 2175 (PVOID*)&Info, 2176 &Mdl); 2177 if (!NT_SUCCESS(Status)) 2178 { 2179 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status); 2180 return Status; 2181 } 2182 2183 /* Calculate how many items we can store */ 2184 Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION); 2185 if (Remaining == 0) 2186 { 2187 goto Leave; 2188 } 2189 2190 /* Copy info from pool lookaside lists */ 2191 ExpCopyLookasideInformation(&Info, 2192 &Remaining, 2193 &ExPoolLookasideListHead, 2194 FALSE); 2195 if (Remaining == 0) 2196 { 2197 goto Leave; 2198 } 2199 2200 /* Copy info from system lookaside lists */ 2201 ExpCopyLookasideInformation(&Info, 2202 &Remaining, 2203 &ExSystemLookasideListHead, 2204 TRUE); 2205 if (Remaining == 0) 2206 { 2207 goto Leave; 2208 } 2209 2210 /* Acquire spinlock for ExpNonPagedLookasideListHead */ 2211 KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql); 2212 2213 /* Copy info from non-paged lookaside lists */ 2214 ExpCopyLookasideInformation(&Info, 2215 &Remaining, 2216 &ExpNonPagedLookasideListHead, 2217 TRUE); 2218 2219 /* Release spinlock for ExpNonPagedLookasideListHead */ 2220 KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); 2221 2222 if (Remaining == 0) 2223 { 2224 goto Leave; 2225 } 2226 2227 /* Acquire spinlock for ExpPagedLookasideListHead */ 2228 KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql); 2229 2230 /* Copy info from paged lookaside lists */ 2231 ExpCopyLookasideInformation(&Info, 2232 &Remaining, 2233 &ExpPagedLookasideListHead, 2234 TRUE); 2235 2236 /* Release spinlock for ExpPagedLookasideListHead */ 2237 KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); 2238 2239 Leave: 2240 2241 /* Release the locked user buffer */ 2242 ExUnlockUserBuffer(Mdl); 2243 2244 /* Return the size of the actually written data */ 2245 *ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION); 2246 return STATUS_SUCCESS; 2247 } 2248 2249 /* Class 46 - Set time slip event */ 2250 SSI_DEF(SystemTimeSlipNotification) 2251 { 2252 /* FIXME */ 2253 DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n"); 2254 return STATUS_NOT_IMPLEMENTED; 2255 } 2256 2257 NTSTATUS 2258 NTAPI 2259 MmSessionCreate(OUT PULONG SessionId); 2260 2261 NTSTATUS 2262 NTAPI 2263 MmSessionDelete(IN ULONG SessionId); 2264 2265 /* Class 47 - Create a new session (TSE) */ 2266 SSI_DEF(SystemSessionCreate) 2267 { 2268 ULONG SessionId; 2269 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 2270 NTSTATUS Status; 2271 2272 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH; 2273 2274 if (PreviousMode != KernelMode) 2275 { 2276 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2277 { 2278 return STATUS_PRIVILEGE_NOT_HELD; 2279 } 2280 2281 ProbeForWriteUlong(Buffer); 2282 } 2283 2284 Status = MmSessionCreate(&SessionId); 2285 if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId; 2286 2287 return Status; 2288 } 2289 2290 /* Class 48 - Delete an existing session (TSE) */ 2291 SSI_DEF(SystemSessionDetach) 2292 { 2293 ULONG SessionId; 2294 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 2295 2296 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH; 2297 2298 if (PreviousMode != KernelMode) 2299 { 2300 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2301 { 2302 return STATUS_PRIVILEGE_NOT_HELD; 2303 } 2304 } 2305 2306 SessionId = *(PULONG)Buffer; 2307 2308 return MmSessionDelete(SessionId); 2309 } 2310 2311 /* Class 49 - UNKNOWN */ 2312 QSI_DEF(SystemSessionInformation) 2313 { 2314 /* FIXME */ 2315 DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n"); 2316 return STATUS_NOT_IMPLEMENTED; 2317 } 2318 2319 /* Class 50 - System range start address */ 2320 QSI_DEF(SystemRangeStartInformation) 2321 { 2322 /* Check user buffer's size */ 2323 if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH; 2324 2325 *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart; 2326 2327 if (ReqSize) *ReqSize = sizeof(ULONG_PTR); 2328 2329 return STATUS_SUCCESS; 2330 } 2331 2332 /* Class 51 - Driver verifier information */ 2333 QSI_DEF(SystemVerifierInformation) 2334 { 2335 /* FIXME */ 2336 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n"); 2337 return STATUS_NOT_IMPLEMENTED; 2338 } 2339 2340 SSI_DEF(SystemVerifierInformation) 2341 { 2342 /* FIXME */ 2343 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n"); 2344 return STATUS_NOT_IMPLEMENTED; 2345 } 2346 2347 /* Class 52 */ 2348 SSI_DEF(SystemVerifierThunkExtend) 2349 { 2350 /* FIXME */ 2351 DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n"); 2352 return STATUS_NOT_IMPLEMENTED; 2353 } 2354 2355 /* Class 53 - A session's processes */ 2356 QSI_DEF(SystemSessionProcessesInformation) 2357 { 2358 /* FIXME */ 2359 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n"); 2360 return STATUS_NOT_IMPLEMENTED; 2361 } 2362 2363 /* Class 54 - Load & map in system space */ 2364 SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation) 2365 { 2366 /* FIXME */ 2367 DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n"); 2368 return STATUS_NOT_IMPLEMENTED; 2369 } 2370 2371 /* Class 55 - NUMA processor information */ 2372 QSI_DEF(SystemNumaProcessorMap) 2373 { 2374 ULONG MaxEntries, Node; 2375 PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer; 2376 2377 /* Validate input size */ 2378 if (Size < sizeof(ULONG)) 2379 { 2380 return STATUS_INFO_LENGTH_MISMATCH; 2381 } 2382 2383 /* Return highest node */ 2384 NumaInformation->HighestNodeNumber = KeNumberNodes - 1; 2385 2386 /* Compute how much entries we will be able to put in output structure */ 2387 MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask)) / sizeof(ULONGLONG); 2388 /* Make sure we don't overflow KeNodeBlock */ 2389 if (MaxEntries > KeNumberNodes) 2390 { 2391 MaxEntries = KeNumberNodes; 2392 } 2393 2394 /* If we have entries to write, and room for it */ 2395 if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) && 2396 MaxEntries != 0) 2397 { 2398 /* Already set size we return */ 2399 *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) + 2400 MaxEntries * sizeof(ULONGLONG); 2401 2402 /* For each node, return processor mask */ 2403 for (Node = 0; Node < MaxEntries; ++Node) 2404 { 2405 NumaInformation->ActiveProcessorsAffinityMask[Node] = KeNodeBlock[Node]->ProcessorMask; 2406 } 2407 } 2408 else 2409 { 2410 /* We only returned highest node number */ 2411 *ReqSize = sizeof(ULONG); 2412 } 2413 2414 return STATUS_SUCCESS; 2415 } 2416 2417 /* Class 56 - Prefetcher information */ 2418 QSI_DEF(SystemPrefetcherInformation) 2419 { 2420 /* FIXME */ 2421 DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n"); 2422 return STATUS_NOT_IMPLEMENTED; 2423 } 2424 2425 /* Class 57 - Extended process information */ 2426 QSI_DEF(SystemExtendedProcessInformation) 2427 { 2428 /* FIXME */ 2429 DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n"); 2430 return STATUS_NOT_IMPLEMENTED; 2431 } 2432 2433 /* Class 58 - Recommended shared data alignment */ 2434 QSI_DEF(SystemRecommendedSharedDataAlignment) 2435 { 2436 /* FIXME */ 2437 DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n"); 2438 return STATUS_NOT_IMPLEMENTED; 2439 } 2440 2441 /* Class 60 - NUMA memory information */ 2442 QSI_DEF(SystemNumaAvailableMemory) 2443 { 2444 ULONG MaxEntries, Node; 2445 PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer; 2446 2447 /* Validate input size */ 2448 if (Size < sizeof(ULONG)) 2449 { 2450 return STATUS_INFO_LENGTH_MISMATCH; 2451 } 2452 2453 /* Return highest node */ 2454 NumaInformation->HighestNodeNumber = KeNumberNodes - 1; 2455 2456 /* Compute how much entries we will be able to put in output structure */ 2457 MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory)) / sizeof(ULONGLONG); 2458 /* Make sure we don't overflow KeNodeBlock */ 2459 if (MaxEntries > KeNumberNodes) 2460 { 2461 MaxEntries = KeNumberNodes; 2462 } 2463 2464 /* If we have entries to write, and room for it */ 2465 if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) && 2466 MaxEntries != 0) 2467 { 2468 /* Already set size we return */ 2469 *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, AvailableMemory) + 2470 MaxEntries * sizeof(ULONGLONG); 2471 2472 /* If we have a single entry (us), directly return MM information */ 2473 if (MaxEntries == 1) 2474 { 2475 NumaInformation->AvailableMemory[0] = MmAvailablePages << PAGE_SHIFT; 2476 } 2477 else 2478 { 2479 /* Otherwise, for each node, return available bytes */ 2480 for (Node = 0; Node < MaxEntries; ++Node) 2481 { 2482 NumaInformation->AvailableMemory[Node] = (KeNodeBlock[Node]->FreeCount[0] + KeNodeBlock[Node]->FreeCount[1]) << PAGE_SHIFT; 2483 } 2484 } 2485 } 2486 else 2487 { 2488 /* We only returned highest node number */ 2489 *ReqSize = sizeof(ULONG); 2490 } 2491 2492 return STATUS_SUCCESS; 2493 } 2494 2495 /* Class 64 - Extended handle information */ 2496 QSI_DEF(SystemExtendedHandleInformation) 2497 { 2498 PSYSTEM_HANDLE_INFORMATION_EX HandleInformation; 2499 PLIST_ENTRY NextTableEntry; 2500 PHANDLE_TABLE HandleTable; 2501 PHANDLE_TABLE_ENTRY HandleTableEntry; 2502 EXHANDLE Handle; 2503 ULONG Index = 0; 2504 NTSTATUS Status; 2505 PMDL Mdl; 2506 PAGED_CODE(); 2507 2508 DPRINT("NtQuerySystemInformation - SystemExtendedHandleInformation\n"); 2509 2510 /* Set initial required buffer size */ 2511 *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION_EX, Handle); 2512 2513 /* Check user's buffer size */ 2514 if (Size < *ReqSize) 2515 { 2516 return STATUS_INFO_LENGTH_MISMATCH; 2517 } 2518 2519 /* We need to lock down the memory */ 2520 Status = ExLockUserBuffer(Buffer, 2521 Size, 2522 ExGetPreviousMode(), 2523 IoWriteAccess, 2524 (PVOID*)&HandleInformation, 2525 &Mdl); 2526 if (!NT_SUCCESS(Status)) 2527 { 2528 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status); 2529 return Status; 2530 } 2531 2532 /* Reset of count of handles */ 2533 HandleInformation->Count = 0; 2534 2535 /* Enter a critical region */ 2536 KeEnterCriticalRegion(); 2537 2538 /* Acquire the handle table lock */ 2539 ExAcquirePushLockShared(&HandleTableListLock); 2540 2541 /* Enumerate all system handles */ 2542 for (NextTableEntry = HandleTableListHead.Flink; 2543 NextTableEntry != &HandleTableListHead; 2544 NextTableEntry = NextTableEntry->Flink) 2545 { 2546 /* Get current handle table */ 2547 HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList); 2548 2549 /* Set the initial value and loop the entries */ 2550 Handle.Value = 0; 2551 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) 2552 { 2553 /* Validate the entry */ 2554 if ((HandleTableEntry->Object) && 2555 (HandleTableEntry->NextFreeTableEntry != -2)) 2556 { 2557 /* Increase of count of handles */ 2558 ++HandleInformation->Count; 2559 2560 /* Lock the entry */ 2561 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 2562 { 2563 /* Increase required buffer size */ 2564 *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX); 2565 2566 /* Check user's buffer size */ 2567 if (*ReqSize > Size) 2568 { 2569 Status = STATUS_INFO_LENGTH_MISMATCH; 2570 } 2571 else 2572 { 2573 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); 2574 2575 /* Filling handle information */ 2576 HandleInformation->Handle[Index].UniqueProcessId = 2577 (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId; 2578 2579 HandleInformation->Handle[Index].CreatorBackTraceIndex = 0; 2580 2581 #if 0 /* FIXME!!! Type field corrupted */ 2582 HandleInformation->Handles[Index].ObjectTypeIndex = 2583 (UCHAR) ObjectHeader->Type->Index; 2584 #else 2585 HandleInformation->Handle[Index].ObjectTypeIndex = 0; 2586 #endif 2587 2588 HandleInformation->Handle[Index].HandleAttributes = 2589 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 2590 2591 HandleInformation->Handle[Index].HandleValue = 2592 (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay; 2593 2594 HandleInformation->Handle[Index].Object = &ObjectHeader->Body; 2595 2596 HandleInformation->Handle[Index].GrantedAccess = 2597 HandleTableEntry->GrantedAccess; 2598 2599 HandleInformation->Handle[Index].Reserved = 0; 2600 2601 ++Index; 2602 } 2603 2604 /* Unlock it */ 2605 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); 2606 } 2607 } 2608 2609 /* Go to the next entry */ 2610 Handle.Value += sizeof(HANDLE); 2611 } 2612 } 2613 2614 /* Release the lock */ 2615 ExReleasePushLockShared(&HandleTableListLock); 2616 2617 /* Leave the critical region */ 2618 KeLeaveCriticalRegion(); 2619 2620 /* Release the locked user buffer */ 2621 ExUnlockUserBuffer(Mdl); 2622 2623 return Status; 2624 } 2625 2626 /* Class 70 - System object security mode information */ 2627 QSI_DEF(SystemObjectSecurityMode) 2628 { 2629 PULONG ObjectSecurityInfo = (PULONG)Buffer; 2630 2631 /* Validate input size */ 2632 if (Size != sizeof(ULONG)) 2633 { 2634 return STATUS_INFO_LENGTH_MISMATCH; 2635 } 2636 2637 *ObjectSecurityInfo = ObpObjectSecurityMode; 2638 2639 return STATUS_SUCCESS; 2640 } 2641 2642 /* Class 73 - Logical processor information */ 2643 QSI_DEF(SystemLogicalProcessorInformation) 2644 { 2645 LONG i; 2646 PKPRCB Prcb; 2647 KAFFINITY CurrentProc; 2648 NTSTATUS Status = STATUS_SUCCESS; 2649 ULONG DataSize = 0, ProcessorFlags; 2650 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION CurrentInfo; 2651 2652 /* First, browse active processors, thanks to the map */ 2653 i = 0; 2654 CurrentInfo = Buffer; 2655 CurrentProc = KeActiveProcessors; 2656 do 2657 { 2658 /* If current processor is active and is main in case of HT/MC, return it */ 2659 Prcb = KiProcessorBlock[i]; 2660 if ((CurrentProc & 1) && 2661 Prcb == Prcb->MultiThreadSetMaster) 2662 { 2663 /* Assume processor can do HT or multicore */ 2664 ProcessorFlags = 1; 2665 2666 /* If set is the same for PRCB and multithread, then 2667 * actually, the processor is single core 2668 */ 2669 if (Prcb->SetMember == Prcb->MultiThreadProcessorSet) 2670 { 2671 ProcessorFlags = 0; 2672 } 2673 2674 /* Check we have enough room to return */ 2675 DataSize += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); 2676 if (DataSize > Size) 2677 { 2678 Status = STATUS_INFO_LENGTH_MISMATCH; 2679 } 2680 else 2681 { 2682 /* Zero output and return */ 2683 RtlZeroMemory(CurrentInfo, sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 2684 CurrentInfo->ProcessorMask = Prcb->MultiThreadProcessorSet; 2685 2686 /* Processor core needs 1 if HT/MC is supported */ 2687 CurrentInfo->Relationship = RelationProcessorCore; 2688 CurrentInfo->ProcessorCore.Flags = ProcessorFlags; 2689 ++CurrentInfo; 2690 } 2691 } 2692 2693 /* Move to the next proc */ 2694 CurrentProc >>= 1; 2695 ++i; 2696 /* Loop while there's someone in the bitmask */ 2697 } while (CurrentProc != 0); 2698 2699 /* Now, return the NUMA nodes */ 2700 for (i = 0; i < KeNumberNodes; ++i) 2701 { 2702 /* Check we have enough room to return */ 2703 DataSize += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); 2704 if (DataSize > Size) 2705 { 2706 Status = STATUS_INFO_LENGTH_MISMATCH; 2707 } 2708 else 2709 { 2710 /* Zero output and return */ 2711 RtlZeroMemory(CurrentInfo, sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 2712 CurrentInfo->ProcessorMask = KeActiveProcessors; 2713 2714 /* NUMA node needs its ID */ 2715 CurrentInfo->Relationship = RelationNumaNode; 2716 CurrentInfo->NumaNode.NodeNumber = i; 2717 ++CurrentInfo; 2718 } 2719 } 2720 2721 *ReqSize = DataSize; 2722 2723 return Status; 2724 } 2725 2726 /* Class 76 - System firmware table information */ 2727 QSI_DEF(SystemFirmwareTableInformation) 2728 { 2729 PSYSTEM_FIRMWARE_TABLE_INFORMATION SysFirmwareInfo = (PSYSTEM_FIRMWARE_TABLE_INFORMATION)Buffer; 2730 NTSTATUS Status = STATUS_SUCCESS; 2731 ULONG InputBufSize; 2732 ULONG DataSize = 0; 2733 ULONG TableCount = 0; 2734 2735 DPRINT("NtQuerySystemInformation - SystemFirmwareTableInformation\n"); 2736 2737 /* Set initial required buffer size */ 2738 *ReqSize = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); 2739 2740 /* Check user's buffer size */ 2741 if (Size < *ReqSize) 2742 { 2743 return STATUS_INFO_LENGTH_MISMATCH; 2744 } 2745 2746 InputBufSize = SysFirmwareInfo->TableBufferLength; 2747 switch (SysFirmwareInfo->ProviderSignature) 2748 { 2749 /* 2750 * ExpFirmwareTableResource and ExpFirmwareTableProviderListHead 2751 * variables should be used there somehow... 2752 */ 2753 case SIG_ACPI: 2754 { 2755 /* FIXME: Not implemented yet */ 2756 DPRINT1("ACPI provider not implemented\n"); 2757 Status = STATUS_NOT_IMPLEMENTED; 2758 break; 2759 } 2760 case SIG_FIRM: 2761 { 2762 /* FIXME: Not implemented yet */ 2763 DPRINT1("FIRM provider not implemented\n"); 2764 Status = STATUS_NOT_IMPLEMENTED; 2765 break; 2766 } 2767 case SIG_RSMB: 2768 { 2769 Status = ExpGetRawSMBiosTable(NULL, &DataSize, 0); 2770 if (DataSize > 0) 2771 { 2772 TableCount = 1; 2773 if (SysFirmwareInfo->Action == SystemFirmwareTable_Enumerate) 2774 { 2775 DataSize = TableCount * sizeof(ULONG); 2776 if (DataSize <= InputBufSize) 2777 { 2778 *(ULONG *)SysFirmwareInfo->TableBuffer = 0; 2779 } 2780 } 2781 else if (SysFirmwareInfo->Action == SystemFirmwareTable_Get 2782 && DataSize <= InputBufSize) 2783 { 2784 Status = ExpGetRawSMBiosTable(SysFirmwareInfo->TableBuffer, &DataSize, InputBufSize); 2785 } 2786 SysFirmwareInfo->TableBufferLength = DataSize; 2787 } 2788 break; 2789 } 2790 default: 2791 { 2792 DPRINT1("SystemFirmwareTableInformation: Unsupported provider (0x%x)\n", 2793 SysFirmwareInfo->ProviderSignature); 2794 Status = STATUS_ILLEGAL_FUNCTION; 2795 } 2796 } 2797 2798 if (NT_SUCCESS(Status)) 2799 { 2800 switch (SysFirmwareInfo->Action) 2801 { 2802 case SystemFirmwareTable_Enumerate: 2803 case SystemFirmwareTable_Get: 2804 { 2805 if (SysFirmwareInfo->TableBufferLength > InputBufSize) 2806 { 2807 Status = STATUS_BUFFER_TOO_SMALL; 2808 } 2809 break; 2810 } 2811 default: 2812 { 2813 DPRINT1("SystemFirmwareTableInformation: Unsupported action (0x%x)\n", 2814 SysFirmwareInfo->Action); 2815 Status = STATUS_ILLEGAL_FUNCTION; 2816 } 2817 } 2818 } 2819 else 2820 { 2821 SysFirmwareInfo->TableBufferLength = 0; 2822 } 2823 return Status; 2824 } 2825 2826 /* Query/Set Calls Table */ 2827 typedef 2828 struct _QSSI_CALLS 2829 { 2830 NTSTATUS (* Query) (PVOID,ULONG,PULONG); 2831 NTSTATUS (* Set) (PVOID,ULONG); 2832 } QSSI_CALLS; 2833 2834 // QS Query & Set 2835 // QX Query 2836 // XS Set 2837 // XX unknown behaviour 2838 // 2839 #define SI_QS(n) {QSI_USE(n),SSI_USE(n)} 2840 #define SI_QX(n) {QSI_USE(n),NULL} 2841 #define SI_XS(n) {NULL,SSI_USE(n)} 2842 #define SI_XX(n) {NULL,NULL} 2843 2844 static 2845 QSSI_CALLS 2846 CallQS[] = 2847 { 2848 SI_QX(SystemBasicInformation), 2849 SI_QX(SystemProcessorInformation), 2850 SI_QX(SystemPerformanceInformation), 2851 SI_QX(SystemTimeOfDayInformation), 2852 SI_QX(SystemPathInformation), 2853 SI_QX(SystemProcessInformation), 2854 SI_QX(SystemCallCountInformation), 2855 SI_QX(SystemDeviceInformation), 2856 SI_QX(SystemProcessorPerformanceInformation), 2857 SI_QS(SystemFlagsInformation), 2858 SI_QX(SystemCallTimeInformation), /* should be SI_XX */ 2859 SI_QX(SystemModuleInformation), 2860 SI_QX(SystemLocksInformation), 2861 SI_QX(SystemStackTraceInformation), /* should be SI_XX */ 2862 SI_QX(SystemPagedPoolInformation), /* should be SI_XX */ 2863 SI_QX(SystemNonPagedPoolInformation), /* should be SI_XX */ 2864 SI_QX(SystemHandleInformation), 2865 SI_QX(SystemObjectInformation), 2866 SI_QX(SystemPageFileInformation), 2867 SI_QX(SystemVdmInstemulInformation), 2868 SI_QX(SystemVdmBopInformation), /* it should be SI_XX */ 2869 SI_QS(SystemFileCacheInformation), 2870 SI_QX(SystemPoolTagInformation), 2871 SI_QX(SystemInterruptInformation), 2872 SI_QS(SystemDpcBehaviourInformation), 2873 SI_QX(SystemFullMemoryInformation), /* it should be SI_XX */ 2874 SI_XS(SystemLoadGdiDriverInformation), 2875 SI_XS(SystemUnloadGdiDriverInformation), 2876 SI_QS(SystemTimeAdjustmentInformation), 2877 SI_QX(SystemSummaryMemoryInformation), /* it should be SI_XX */ 2878 SI_QX(SystemNextEventIdInformation), /* it should be SI_XX */ 2879 SI_QX(SystemPerformanceTraceInformation), /* it should be SI_XX */ 2880 SI_QX(SystemCrashDumpInformation), 2881 SI_QX(SystemExceptionInformation), 2882 SI_QX(SystemCrashDumpStateInformation), 2883 SI_QX(SystemKernelDebuggerInformation), 2884 SI_QX(SystemContextSwitchInformation), 2885 SI_QS(SystemRegistryQuotaInformation), 2886 SI_XS(SystemExtendServiceTableInformation), 2887 SI_XS(SystemPrioritySeperation), 2888 SI_QX(SystemVerifierAddDriverInformation), /* it should be SI_XX */ 2889 SI_QX(SystemVerifierRemoveDriverInformation), /* it should be SI_XX */ 2890 SI_QX(SystemProcessorIdleInformation), /* it should be SI_XX */ 2891 SI_QX(SystemLegacyDriverInformation), /* it should be SI_XX */ 2892 SI_QS(SystemCurrentTimeZoneInformation), /* it should be SI_QX */ 2893 SI_QX(SystemLookasideInformation), 2894 SI_XS(SystemTimeSlipNotification), 2895 SI_XS(SystemSessionCreate), 2896 SI_XS(SystemSessionDetach), 2897 SI_QX(SystemSessionInformation), /* it should be SI_XX */ 2898 SI_QX(SystemRangeStartInformation), 2899 SI_QS(SystemVerifierInformation), 2900 SI_XS(SystemVerifierThunkExtend), 2901 SI_QX(SystemSessionProcessesInformation), 2902 SI_XS(SystemLoadGdiDriverInSystemSpaceInformation), 2903 SI_QX(SystemNumaProcessorMap), 2904 SI_QX(SystemPrefetcherInformation), 2905 SI_QX(SystemExtendedProcessInformation), 2906 SI_QX(SystemRecommendedSharedDataAlignment), 2907 SI_XX(SystemComPlusPackage), 2908 SI_QX(SystemNumaAvailableMemory), 2909 SI_XX(SystemProcessorPowerInformation), /* FIXME: not implemented */ 2910 SI_XX(SystemEmulationBasicInformation), /* FIXME: not implemented */ 2911 SI_XX(SystemEmulationProcessorInformation), /* FIXME: not implemented */ 2912 SI_QX(SystemExtendedHandleInformation), 2913 SI_XX(SystemLostDelayedWriteInformation), /* FIXME: not implemented */ 2914 SI_XX(SystemBigPoolInformation), /* FIXME: not implemented */ 2915 SI_XX(SystemSessionPoolTagInformation), /* FIXME: not implemented */ 2916 SI_XX(SystemSessionMappedViewInformation), /* FIXME: not implemented */ 2917 SI_XX(SystemHotpatchInformation), /* FIXME: not implemented */ 2918 SI_QX(SystemObjectSecurityMode), 2919 SI_XX(SystemWatchdogTimerHandler), /* FIXME: not implemented */ 2920 SI_XX(SystemWatchdogTimerInformation), /* FIXME: not implemented */ 2921 SI_QX(SystemLogicalProcessorInformation), 2922 SI_XX(SystemWow64SharedInformation), /* FIXME: not implemented */ 2923 SI_XX(SystemRegisterFirmwareTableInformationHandler), /* FIXME: not implemented */ 2924 SI_QX(SystemFirmwareTableInformation), 2925 }; 2926 2927 C_ASSERT(SystemBasicInformation == 0); 2928 #define MIN_SYSTEM_INFO_CLASS (SystemBasicInformation) 2929 #define MAX_SYSTEM_INFO_CLASS RTL_NUMBER_OF(CallQS) 2930 2931 /* 2932 * @implemented 2933 */ 2934 __kernel_entry 2935 NTSTATUS 2936 NTAPI 2937 NtQuerySystemInformation( 2938 _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 2939 _Out_writes_bytes_to_opt_(SystemInformationLength, *ReturnLength) PVOID SystemInformation, 2940 _In_ ULONG SystemInformationLength, 2941 _Out_opt_ PULONG ReturnLength) 2942 { 2943 NTSTATUS Status = STATUS_NOT_IMPLEMENTED; 2944 ULONG CapturedResultLength = 0; 2945 ULONG Alignment = TYPE_ALIGNMENT(ULONG); 2946 KPROCESSOR_MODE PreviousMode; 2947 2948 PAGED_CODE(); 2949 2950 PreviousMode = ExGetPreviousMode(); 2951 2952 _SEH2_TRY 2953 { 2954 #if (NTDDI_VERSION >= NTDDI_VISTA) 2955 /* 2956 * Check whether the request is valid. 2957 */ 2958 if (SystemInformationClass < MIN_SYSTEM_INFO_CLASS || 2959 SystemInformationClass >= MAX_SYSTEM_INFO_CLASS) 2960 { 2961 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS); 2962 } 2963 #endif 2964 2965 if (PreviousMode != KernelMode) 2966 { 2967 /* SystemKernelDebuggerInformation needs only BOOLEAN alignment */ 2968 if (SystemInformationClass == SystemKernelDebuggerInformation) 2969 Alignment = TYPE_ALIGNMENT(BOOLEAN); 2970 2971 ProbeForWrite(SystemInformation, SystemInformationLength, Alignment); 2972 if (ReturnLength != NULL) 2973 ProbeForWriteUlong(ReturnLength); 2974 } 2975 2976 if (ReturnLength) 2977 *ReturnLength = 0; 2978 2979 #if (NTDDI_VERSION < NTDDI_VISTA) 2980 /* 2981 * Check whether the request is valid. 2982 */ 2983 if (SystemInformationClass < MIN_SYSTEM_INFO_CLASS || 2984 SystemInformationClass >= MAX_SYSTEM_INFO_CLASS) 2985 { 2986 _SEH2_YIELD(return STATUS_INVALID_INFO_CLASS); 2987 } 2988 #endif 2989 2990 if (CallQS[SystemInformationClass].Query != NULL) 2991 { 2992 /* Hand the request to a subhandler */ 2993 Status = CallQS[SystemInformationClass].Query(SystemInformation, 2994 SystemInformationLength, 2995 &CapturedResultLength); 2996 2997 /* Save the result length to the caller */ 2998 if (ReturnLength) 2999 *ReturnLength = CapturedResultLength; 3000 } 3001 } 3002 _SEH2_EXCEPT(ExSystemExceptionFilter()) 3003 { 3004 Status = _SEH2_GetExceptionCode(); 3005 } 3006 _SEH2_END; 3007 3008 return Status; 3009 } 3010 3011 __kernel_entry 3012 NTSTATUS 3013 NTAPI 3014 NtSetSystemInformation( 3015 _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 3016 _In_reads_bytes_(SystemInformationLength) PVOID SystemInformation, 3017 _In_ ULONG SystemInformationLength) 3018 { 3019 NTSTATUS Status = STATUS_INVALID_INFO_CLASS; 3020 KPROCESSOR_MODE PreviousMode; 3021 3022 PAGED_CODE(); 3023 3024 PreviousMode = ExGetPreviousMode(); 3025 3026 _SEH2_TRY 3027 { 3028 /* 3029 * If called from user mode, check possible unsafe arguments. 3030 */ 3031 if (PreviousMode != KernelMode) 3032 { 3033 ProbeForRead(SystemInformation, SystemInformationLength, sizeof(ULONG)); 3034 } 3035 3036 /* 3037 * Check whether the request is valid. 3038 */ 3039 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) && 3040 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS)) 3041 { 3042 if (CallQS[SystemInformationClass].Set != NULL) 3043 { 3044 /* Hand the request to a subhandler */ 3045 Status = CallQS[SystemInformationClass].Set(SystemInformation, 3046 SystemInformationLength); 3047 } 3048 } 3049 } 3050 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3051 { 3052 Status = _SEH2_GetExceptionCode(); 3053 } 3054 _SEH2_END; 3055 3056 return Status; 3057 } 3058 3059 ULONG 3060 NTAPI 3061 NtGetCurrentProcessorNumber(VOID) 3062 { 3063 /* Just use Ke */ 3064 return KeGetCurrentProcessorNumber(); 3065 } 3066 3067 #undef ExGetPreviousMode 3068 KPROCESSOR_MODE 3069 NTAPI 3070 ExGetPreviousMode(VOID) 3071 { 3072 /* Just use Ke */ 3073 return KeGetPreviousMode(); 3074 } 3075