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