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