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