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 */ 865 QSI_DEF(SystemPathInformation) 866 { 867 /* FIXME: QSI returns STATUS_BREAKPOINT. Why? */ 868 DPRINT1("NtQuerySystemInformation - SystemPathInformation not implemented\n"); 869 870 return STATUS_BREAKPOINT; 871 } 872 873 /* Class 5 - Process Information */ 874 QSI_DEF(SystemProcessInformation) 875 { 876 PSYSTEM_PROCESS_INFORMATION SpiCurrent; 877 PSYSTEM_THREAD_INFORMATION ThreadInfo; 878 PEPROCESS Process = NULL, SystemProcess; 879 PETHREAD CurrentThread; 880 ANSI_STRING ImageName; 881 ULONG CurrentSize; 882 USHORT ImageNameMaximumLength; // image name length in bytes 883 USHORT ImageNameLength; 884 PLIST_ENTRY CurrentEntry; 885 ULONG TotalSize = 0, ThreadsCount; 886 ULONG TotalUser, TotalKernel; 887 PUCHAR Current; 888 NTSTATUS Status = STATUS_SUCCESS; 889 PUNICODE_STRING TempProcessImageName; 890 _SEH2_VOLATILE PUNICODE_STRING ProcessImageName = NULL; 891 PWCHAR szSrc; 892 BOOLEAN Overflow = FALSE; 893 894 _SEH2_TRY 895 { 896 /* scan the process list */ 897 898 PSYSTEM_PROCESS_INFORMATION Spi 899 = (PSYSTEM_PROCESS_INFORMATION) Buffer; 900 901 *ReqSize = sizeof(SYSTEM_PROCESS_INFORMATION); 902 903 /* Check for overflow */ 904 if (Size < sizeof(SYSTEM_PROCESS_INFORMATION)) 905 { 906 Overflow = TRUE; 907 } 908 909 /* Zero user's buffer */ 910 if (!Overflow) RtlZeroMemory(Spi, Size); 911 912 SystemProcess = PsIdleProcess; 913 Process = SystemProcess; 914 Current = (PUCHAR) Spi; 915 916 do 917 { 918 SpiCurrent = (PSYSTEM_PROCESS_INFORMATION) Current; 919 920 /* Lock the Process */ 921 KeEnterCriticalRegion(); 922 ExAcquirePushLockShared(&Process->ProcessLock); 923 924 if ((Process->ProcessExiting) && 925 (Process->Pcb.Header.SignalState) && 926 !(Process->ActiveThreads) && 927 (IsListEmpty(&Process->Pcb.ThreadListHead))) 928 { 929 DPRINT1("Process %p (%s:%p) is a zombie\n", 930 Process, Process->ImageFileName, Process->UniqueProcessId); 931 CurrentSize = 0; 932 ImageNameMaximumLength = 0; 933 934 /* Unlock the Process */ 935 ExReleasePushLockShared(&Process->ProcessLock); 936 KeLeaveCriticalRegion(); 937 goto Skip; 938 } 939 940 ThreadsCount = 0; 941 CurrentEntry = Process->Pcb.ThreadListHead.Flink; 942 while (CurrentEntry != &Process->Pcb.ThreadListHead) 943 { 944 ThreadsCount++; 945 CurrentEntry = CurrentEntry->Flink; 946 } 947 948 // size of the structure for every process 949 CurrentSize = sizeof(SYSTEM_PROCESS_INFORMATION) + sizeof(SYSTEM_THREAD_INFORMATION) * ThreadsCount; 950 ImageNameLength = 0; 951 Status = SeLocateProcessImageName(Process, &TempProcessImageName); 952 ProcessImageName = TempProcessImageName; 953 szSrc = NULL; 954 if (NT_SUCCESS(Status) && (ProcessImageName->Length > 0)) 955 { 956 szSrc = (PWCHAR)((PCHAR)ProcessImageName->Buffer + ProcessImageName->Length); 957 /* Loop the file name*/ 958 while (szSrc > ProcessImageName->Buffer) 959 { 960 /* Make sure this isn't a backslash */ 961 if (*--szSrc == OBJ_NAME_PATH_SEPARATOR) 962 { 963 szSrc++; 964 break; 965 } 966 else 967 { 968 ImageNameLength += sizeof(WCHAR); 969 } 970 } 971 } 972 if (!ImageNameLength && Process != PsIdleProcess) 973 { 974 ImageNameLength = (USHORT)strlen(Process->ImageFileName) * sizeof(WCHAR); 975 } 976 977 /* Round up the image name length as NT does */ 978 if (ImageNameLength > 0) 979 ImageNameMaximumLength = ROUND_UP(ImageNameLength + sizeof(WCHAR), 8); 980 else 981 ImageNameMaximumLength = 0; 982 983 TotalSize += CurrentSize + ImageNameMaximumLength; 984 985 /* Check for overflow */ 986 if (TotalSize > Size) 987 { 988 Overflow = TRUE; 989 } 990 991 /* Fill system information */ 992 if (!Overflow) 993 { 994 SpiCurrent->NextEntryOffset = CurrentSize + ImageNameMaximumLength; // relative offset to the beginning of the next structure 995 SpiCurrent->NumberOfThreads = ThreadsCount; 996 SpiCurrent->CreateTime = Process->CreateTime; 997 SpiCurrent->ImageName.Length = ImageNameLength; 998 SpiCurrent->ImageName.MaximumLength = ImageNameMaximumLength; 999 SpiCurrent->ImageName.Buffer = (void*)(Current + CurrentSize); 1000 1001 /* Copy name to the end of the struct */ 1002 if(Process != PsIdleProcess) 1003 { 1004 if (szSrc) 1005 { 1006 RtlCopyMemory(SpiCurrent->ImageName.Buffer, szSrc, SpiCurrent->ImageName.Length); 1007 } 1008 else 1009 { 1010 RtlInitAnsiString(&ImageName, Process->ImageFileName); 1011 RtlAnsiStringToUnicodeString(&SpiCurrent->ImageName, &ImageName, FALSE); 1012 } 1013 } 1014 else 1015 { 1016 RtlInitUnicodeString(&SpiCurrent->ImageName, NULL); 1017 } 1018 1019 SpiCurrent->BasePriority = Process->Pcb.BasePriority; 1020 SpiCurrent->UniqueProcessId = Process->UniqueProcessId; 1021 SpiCurrent->InheritedFromUniqueProcessId = Process->InheritedFromUniqueProcessId; 1022 SpiCurrent->HandleCount = ObGetProcessHandleCount(Process); 1023 SpiCurrent->PeakVirtualSize = Process->PeakVirtualSize; 1024 SpiCurrent->VirtualSize = Process->VirtualSize; 1025 SpiCurrent->PageFaultCount = Process->Vm.PageFaultCount; 1026 SpiCurrent->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize; 1027 SpiCurrent->WorkingSetSize = Process->Vm.WorkingSetSize; 1028 SpiCurrent->QuotaPeakPagedPoolUsage = Process->QuotaPeak[PsPagedPool]; 1029 SpiCurrent->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool]; 1030 SpiCurrent->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[PsNonPagedPool]; 1031 SpiCurrent->QuotaNonPagedPoolUsage = Process->QuotaUsage[PsNonPagedPool]; 1032 SpiCurrent->PagefileUsage = Process->QuotaUsage[PsPageFile]; 1033 SpiCurrent->PeakPagefileUsage = Process->QuotaPeak[PsPageFile]; 1034 SpiCurrent->PrivatePageCount = Process->CommitCharge; 1035 ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(SpiCurrent + 1); 1036 1037 CurrentEntry = Process->Pcb.ThreadListHead.Flink; 1038 while (CurrentEntry != &Process->Pcb.ThreadListHead) 1039 { 1040 CurrentThread = CONTAINING_RECORD(CurrentEntry, ETHREAD, Tcb.ThreadListEntry); 1041 1042 ThreadInfo->KernelTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.KernelTime, KeMaximumIncrement); 1043 ThreadInfo->UserTime.QuadPart = UInt32x32To64(CurrentThread->Tcb.UserTime, KeMaximumIncrement); 1044 ThreadInfo->CreateTime.QuadPart = CurrentThread->CreateTime.QuadPart; 1045 ThreadInfo->WaitTime = CurrentThread->Tcb.WaitTime; 1046 ThreadInfo->StartAddress = (PVOID) CurrentThread->StartAddress; 1047 ThreadInfo->ClientId = CurrentThread->Cid; 1048 ThreadInfo->Priority = CurrentThread->Tcb.Priority; 1049 ThreadInfo->BasePriority = CurrentThread->Tcb.BasePriority; 1050 ThreadInfo->ContextSwitches = CurrentThread->Tcb.ContextSwitches; 1051 ThreadInfo->ThreadState = CurrentThread->Tcb.State; 1052 ThreadInfo->WaitReason = CurrentThread->Tcb.WaitReason; 1053 1054 ThreadInfo++; 1055 CurrentEntry = CurrentEntry->Flink; 1056 } 1057 1058 /* Query total user/kernel times of a process */ 1059 TotalKernel = KeQueryRuntimeProcess(&Process->Pcb, &TotalUser); 1060 SpiCurrent->UserTime.QuadPart = UInt32x32To64(TotalUser, KeMaximumIncrement); 1061 SpiCurrent->KernelTime.QuadPart = UInt32x32To64(TotalKernel, KeMaximumIncrement); 1062 } 1063 1064 if (ProcessImageName) 1065 { 1066 /* Release the memory allocated by SeLocateProcessImageName */ 1067 ExFreePoolWithTag(ProcessImageName, TAG_SEPA); 1068 ProcessImageName = NULL; 1069 } 1070 1071 /* Unlock the Process */ 1072 ExReleasePushLockShared(&Process->ProcessLock); 1073 KeLeaveCriticalRegion(); 1074 1075 /* Handle idle process entry */ 1076 Skip: 1077 if (Process == PsIdleProcess) Process = NULL; 1078 1079 Process = PsGetNextProcess(Process); 1080 ThreadsCount = 0; 1081 if ((Process == SystemProcess) || (Process == NULL)) 1082 { 1083 if (!Overflow) 1084 SpiCurrent->NextEntryOffset = 0; 1085 break; 1086 } 1087 else 1088 Current += CurrentSize + ImageNameMaximumLength; 1089 } while ((Process != SystemProcess) && (Process != NULL)); 1090 1091 if(Process != NULL) 1092 ObDereferenceObject(Process); 1093 Status = STATUS_SUCCESS; 1094 } 1095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1096 { 1097 if(Process != NULL) 1098 ObDereferenceObject(Process); 1099 if (ProcessImageName) 1100 { 1101 /* Release the memory allocated by SeLocateProcessImageName */ 1102 ExFreePoolWithTag(ProcessImageName, TAG_SEPA); 1103 } 1104 1105 Status = _SEH2_GetExceptionCode(); 1106 } 1107 _SEH2_END 1108 1109 if (Overflow) 1110 Status = STATUS_INFO_LENGTH_MISMATCH; 1111 1112 *ReqSize = TotalSize; 1113 return Status; 1114 } 1115 1116 /* Class 6 - Call Count Information */ 1117 QSI_DEF(SystemCallCountInformation) 1118 { 1119 /* FIXME */ 1120 DPRINT1("NtQuerySystemInformation - SystemCallCountInformation not implemented\n"); 1121 return STATUS_NOT_IMPLEMENTED; 1122 } 1123 1124 /* Class 7 - Device Information */ 1125 QSI_DEF(SystemDeviceInformation) 1126 { 1127 PSYSTEM_DEVICE_INFORMATION Sdi 1128 = (PSYSTEM_DEVICE_INFORMATION) Buffer; 1129 PCONFIGURATION_INFORMATION ConfigInfo; 1130 1131 *ReqSize = sizeof(SYSTEM_DEVICE_INFORMATION); 1132 1133 /* Check user buffer's size */ 1134 if (Size < sizeof(SYSTEM_DEVICE_INFORMATION)) 1135 { 1136 return STATUS_INFO_LENGTH_MISMATCH; 1137 } 1138 1139 ConfigInfo = IoGetConfigurationInformation(); 1140 1141 Sdi->NumberOfDisks = ConfigInfo->DiskCount; 1142 Sdi->NumberOfFloppies = ConfigInfo->FloppyCount; 1143 Sdi->NumberOfCdRoms = ConfigInfo->CdRomCount; 1144 Sdi->NumberOfTapes = ConfigInfo->TapeCount; 1145 Sdi->NumberOfSerialPorts = ConfigInfo->SerialCount; 1146 Sdi->NumberOfParallelPorts = ConfigInfo->ParallelCount; 1147 1148 return STATUS_SUCCESS; 1149 } 1150 1151 /* Class 8 - Processor Performance Information */ 1152 QSI_DEF(SystemProcessorPerformanceInformation) 1153 { 1154 PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Spi 1155 = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) Buffer; 1156 1157 LONG i; 1158 ULONG TotalTime; 1159 PKPRCB Prcb; 1160 1161 *ReqSize = KeNumberProcessors * sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); 1162 1163 /* Check user buffer's size */ 1164 if (Size < *ReqSize) 1165 { 1166 return STATUS_INFO_LENGTH_MISMATCH; 1167 } 1168 1169 for (i = 0; i < KeNumberProcessors; i++) 1170 { 1171 /* Get the PRCB on this processor */ 1172 Prcb = KiProcessorBlock[i]; 1173 1174 /* Calculate total user and kernel times */ 1175 TotalTime = Prcb->IdleThread->KernelTime + Prcb->IdleThread->UserTime; 1176 Spi->IdleTime.QuadPart = UInt32x32To64(TotalTime, KeMaximumIncrement); 1177 Spi->KernelTime.QuadPart = UInt32x32To64(Prcb->KernelTime, KeMaximumIncrement); 1178 Spi->UserTime.QuadPart = UInt32x32To64(Prcb->UserTime, KeMaximumIncrement); 1179 Spi->DpcTime.QuadPart = UInt32x32To64(Prcb->DpcTime, KeMaximumIncrement); 1180 Spi->InterruptTime.QuadPart = UInt32x32To64(Prcb->InterruptTime, KeMaximumIncrement); 1181 Spi->InterruptCount = Prcb->InterruptCount; 1182 Spi++; 1183 } 1184 1185 return STATUS_SUCCESS; 1186 } 1187 1188 /* Class 9 - Flags Information */ 1189 QSI_DEF(SystemFlagsInformation) 1190 { 1191 #if (NTDDI_VERSION >= NTDDI_VISTA) 1192 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION); 1193 #endif 1194 1195 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size) 1196 { 1197 return STATUS_INFO_LENGTH_MISMATCH; 1198 } 1199 1200 ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags = NtGlobalFlag; 1201 #if (NTDDI_VERSION < NTDDI_VISTA) 1202 *ReqSize = sizeof(SYSTEM_FLAGS_INFORMATION); 1203 #endif 1204 1205 return STATUS_SUCCESS; 1206 } 1207 1208 SSI_DEF(SystemFlagsInformation) 1209 { 1210 if (sizeof(SYSTEM_FLAGS_INFORMATION) != Size) 1211 { 1212 return STATUS_INFO_LENGTH_MISMATCH; 1213 } 1214 1215 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, ExGetPreviousMode())) 1216 { 1217 return STATUS_ACCESS_DENIED; 1218 } 1219 1220 NtGlobalFlag = ((PSYSTEM_FLAGS_INFORMATION) Buffer)->Flags; 1221 return STATUS_SUCCESS; 1222 } 1223 1224 /* Class 10 - Call Time Information */ 1225 QSI_DEF(SystemCallTimeInformation) 1226 { 1227 /* FIXME */ 1228 DPRINT1("NtQuerySystemInformation - SystemCallTimeInformation not implemented\n"); 1229 return STATUS_NOT_IMPLEMENTED; 1230 } 1231 1232 /* Class 11 - Module Information */ 1233 QSI_DEF(SystemModuleInformation) 1234 { 1235 NTSTATUS Status; 1236 1237 /* Acquire system module list lock */ 1238 KeEnterCriticalRegion(); 1239 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE); 1240 1241 /* Call the generic handler with the system module list */ 1242 Status = ExpQueryModuleInformation(&PsLoadedModuleList, 1243 &MmLoadedUserImageList, 1244 (PRTL_PROCESS_MODULES)Buffer, 1245 Size, 1246 ReqSize); 1247 1248 /* Release list lock and return status */ 1249 ExReleaseResourceLite(&PsLoadedModuleResource); 1250 KeLeaveCriticalRegion(); 1251 return Status; 1252 } 1253 1254 /* Class 12 - Locks Information */ 1255 QSI_DEF(SystemLocksInformation) 1256 { 1257 /* FIXME */ 1258 DPRINT1("NtQuerySystemInformation - SystemLocksInformation not implemented\n"); 1259 return STATUS_NOT_IMPLEMENTED; 1260 } 1261 1262 /* Class 13 - Stack Trace Information */ 1263 QSI_DEF(SystemStackTraceInformation) 1264 { 1265 /* FIXME */ 1266 DPRINT1("NtQuerySystemInformation - SystemStackTraceInformation not implemented\n"); 1267 return STATUS_NOT_IMPLEMENTED; 1268 } 1269 1270 /* Class 14 - Paged Pool Information */ 1271 QSI_DEF(SystemPagedPoolInformation) 1272 { 1273 /* FIXME */ 1274 DPRINT1("NtQuerySystemInformation - SystemPagedPoolInformation not implemented\n"); 1275 return STATUS_NOT_IMPLEMENTED; 1276 } 1277 1278 /* Class 15 - Non Paged Pool Information */ 1279 QSI_DEF(SystemNonPagedPoolInformation) 1280 { 1281 /* FIXME */ 1282 DPRINT1("NtQuerySystemInformation - SystemNonPagedPoolInformation not implemented\n"); 1283 return STATUS_NOT_IMPLEMENTED; 1284 } 1285 1286 1287 /* Class 16 - Handle Information */ 1288 QSI_DEF(SystemHandleInformation) 1289 { 1290 PSYSTEM_HANDLE_INFORMATION HandleInformation; 1291 PLIST_ENTRY NextTableEntry; 1292 PHANDLE_TABLE HandleTable; 1293 PHANDLE_TABLE_ENTRY HandleTableEntry; 1294 EXHANDLE Handle; 1295 ULONG Index = 0; 1296 NTSTATUS Status; 1297 PMDL Mdl; 1298 PAGED_CODE(); 1299 1300 DPRINT("NtQuerySystemInformation - SystemHandleInformation\n"); 1301 1302 /* Set initial required buffer size */ 1303 *ReqSize = FIELD_OFFSET(SYSTEM_HANDLE_INFORMATION, Handles); 1304 1305 /* Check user's buffer size */ 1306 if (Size < *ReqSize) 1307 { 1308 return STATUS_INFO_LENGTH_MISMATCH; 1309 } 1310 1311 /* We need to lock down the memory */ 1312 Status = ExLockUserBuffer(Buffer, 1313 Size, 1314 ExGetPreviousMode(), 1315 IoWriteAccess, 1316 (PVOID*)&HandleInformation, 1317 &Mdl); 1318 if (!NT_SUCCESS(Status)) 1319 { 1320 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status); 1321 return Status; 1322 } 1323 1324 /* Reset of count of handles */ 1325 HandleInformation->NumberOfHandles = 0; 1326 1327 /* Enter a critical region */ 1328 KeEnterCriticalRegion(); 1329 1330 /* Acquire the handle table lock */ 1331 ExAcquirePushLockShared(&HandleTableListLock); 1332 1333 /* Enumerate all system handles */ 1334 for (NextTableEntry = HandleTableListHead.Flink; 1335 NextTableEntry != &HandleTableListHead; 1336 NextTableEntry = NextTableEntry->Flink) 1337 { 1338 /* Get current handle table */ 1339 HandleTable = CONTAINING_RECORD(NextTableEntry, HANDLE_TABLE, HandleTableList); 1340 1341 /* Set the initial value and loop the entries */ 1342 Handle.Value = 0; 1343 while ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, Handle))) 1344 { 1345 /* Validate the entry */ 1346 if ((HandleTableEntry->Object) && 1347 (HandleTableEntry->NextFreeTableEntry != -2)) 1348 { 1349 /* Increase of count of handles */ 1350 ++HandleInformation->NumberOfHandles; 1351 1352 /* Lock the entry */ 1353 if (ExpLockHandleTableEntry(HandleTable, HandleTableEntry)) 1354 { 1355 /* Increase required buffer size */ 1356 *ReqSize += sizeof(SYSTEM_HANDLE_TABLE_ENTRY_INFO); 1357 1358 /* Check user's buffer size */ 1359 if (*ReqSize > Size) 1360 { 1361 Status = STATUS_INFO_LENGTH_MISMATCH; 1362 } 1363 else 1364 { 1365 POBJECT_HEADER ObjectHeader = ObpGetHandleObject(HandleTableEntry); 1366 1367 /* Filling handle information */ 1368 HandleInformation->Handles[Index].UniqueProcessId = 1369 (USHORT)(ULONG_PTR) HandleTable->UniqueProcessId; 1370 1371 HandleInformation->Handles[Index].CreatorBackTraceIndex = 0; 1372 1373 #if 0 /* FIXME!!! Type field currupted */ 1374 HandleInformation->Handles[Index].ObjectTypeIndex = 1375 (UCHAR) ObjectHeader->Type->Index; 1376 #else 1377 HandleInformation->Handles[Index].ObjectTypeIndex = 0; 1378 #endif 1379 1380 HandleInformation->Handles[Index].HandleAttributes = 1381 HandleTableEntry->ObAttributes & OBJ_HANDLE_ATTRIBUTES; 1382 1383 HandleInformation->Handles[Index].HandleValue = 1384 (USHORT)(ULONG_PTR) Handle.GenericHandleOverlay; 1385 1386 HandleInformation->Handles[Index].Object = &ObjectHeader->Body; 1387 1388 HandleInformation->Handles[Index].GrantedAccess = 1389 HandleTableEntry->GrantedAccess; 1390 1391 ++Index; 1392 } 1393 1394 /* Unlock it */ 1395 ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); 1396 } 1397 } 1398 1399 /* Go to the next entry */ 1400 Handle.Value += sizeof(HANDLE); 1401 } 1402 } 1403 1404 /* Release the lock */ 1405 ExReleasePushLockShared(&HandleTableListLock); 1406 1407 /* Leave the critical region */ 1408 KeLeaveCriticalRegion(); 1409 1410 /* Release the locked user buffer */ 1411 ExUnlockUserBuffer(Mdl); 1412 1413 return Status; 1414 } 1415 1416 /* Class 17 - Information */ 1417 QSI_DEF(SystemObjectInformation) 1418 { 1419 /* FIXME */ 1420 DPRINT1("NtQuerySystemInformation - SystemObjectInformation not implemented\n"); 1421 return STATUS_NOT_IMPLEMENTED; 1422 } 1423 1424 /* Class 18 - Information */ 1425 QSI_DEF(SystemPageFileInformation) 1426 { 1427 UNICODE_STRING FileName; /* FIXME */ 1428 SYSTEM_PAGEFILE_INFORMATION *Spfi = (SYSTEM_PAGEFILE_INFORMATION *) Buffer; 1429 1430 if (Size < sizeof(SYSTEM_PAGEFILE_INFORMATION)) 1431 { 1432 * ReqSize = sizeof(SYSTEM_PAGEFILE_INFORMATION); 1433 return STATUS_INFO_LENGTH_MISMATCH; 1434 } 1435 1436 RtlInitUnicodeString(&FileName, NULL); /* FIXME */ 1437 1438 /* FIXME */ 1439 Spfi->NextEntryOffset = 0; 1440 1441 Spfi->TotalSize = MiFreeSwapPages + MiUsedSwapPages; 1442 Spfi->TotalInUse = MiUsedSwapPages; 1443 Spfi->PeakUsage = MiUsedSwapPages; /* FIXME */ 1444 Spfi->PageFileName = FileName; 1445 return STATUS_SUCCESS; 1446 } 1447 1448 /* Class 19 - Vdm Instemul Information */ 1449 QSI_DEF(SystemVdmInstemulInformation) 1450 { 1451 /* FIXME */ 1452 DPRINT1("NtQuerySystemInformation - SystemVdmInstemulInformation not implemented\n"); 1453 return STATUS_NOT_IMPLEMENTED; 1454 } 1455 1456 /* Class 20 - Vdm Bop Information */ 1457 QSI_DEF(SystemVdmBopInformation) 1458 { 1459 /* FIXME */ 1460 DPRINT1("NtQuerySystemInformation - SystemVdmBopInformation not implemented\n"); 1461 return STATUS_NOT_IMPLEMENTED; 1462 } 1463 1464 /* Class 21 - File Cache Information */ 1465 QSI_DEF(SystemFileCacheInformation) 1466 { 1467 SYSTEM_FILECACHE_INFORMATION *Sci = (SYSTEM_FILECACHE_INFORMATION *) Buffer; 1468 1469 *ReqSize = sizeof(SYSTEM_FILECACHE_INFORMATION); 1470 1471 if (Size < *ReqSize) 1472 { 1473 return STATUS_INFO_LENGTH_MISMATCH; 1474 } 1475 1476 RtlZeroMemory(Sci, sizeof(SYSTEM_FILECACHE_INFORMATION)); 1477 1478 /* Return the Byte size not the page size. */ 1479 Sci->CurrentSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */ 1480 Sci->PeakSize = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME */ 1481 /* Taskmgr multiplies this one by page size right away */ 1482 Sci->CurrentSizeIncludingTransitionInPages = MiMemoryConsumers[MC_USER].PagesUsed; /* FIXME: Should be */ 1483 /* system working set and standby pages. */ 1484 Sci->PageFaultCount = 0; /* FIXME */ 1485 Sci->MinimumWorkingSet = 0; /* FIXME */ 1486 Sci->MaximumWorkingSet = 0; /* FIXME */ 1487 1488 return STATUS_SUCCESS; 1489 } 1490 1491 SSI_DEF(SystemFileCacheInformation) 1492 { 1493 if (Size < sizeof(SYSTEM_FILECACHE_INFORMATION)) 1494 { 1495 return STATUS_INFO_LENGTH_MISMATCH; 1496 } 1497 /* FIXME */ 1498 DPRINT1("NtSetSystemInformation - SystemFileCacheInformation not implemented\n"); 1499 return STATUS_NOT_IMPLEMENTED; 1500 } 1501 1502 /* Class 22 - Pool Tag Information */ 1503 QSI_DEF(SystemPoolTagInformation) 1504 { 1505 if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH; 1506 return ExGetPoolTagInfo(Buffer, Size, ReqSize); 1507 } 1508 1509 /* Class 23 - Interrupt Information for all processors */ 1510 QSI_DEF(SystemInterruptInformation) 1511 { 1512 PKPRCB Prcb; 1513 LONG i; 1514 ULONG ti; 1515 PSYSTEM_INTERRUPT_INFORMATION sii = (PSYSTEM_INTERRUPT_INFORMATION)Buffer; 1516 1517 if(Size < KeNumberProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION)) 1518 { 1519 return STATUS_INFO_LENGTH_MISMATCH; 1520 } 1521 1522 ti = KeQueryTimeIncrement(); 1523 1524 for (i = 0; i < KeNumberProcessors; i++) 1525 { 1526 Prcb = KiProcessorBlock[i]; 1527 sii->ContextSwitches = KeGetContextSwitches(Prcb); 1528 sii->DpcCount = Prcb->DpcData[0].DpcCount; 1529 sii->DpcRate = Prcb->DpcRequestRate; 1530 sii->TimeIncrement = ti; 1531 sii->DpcBypassCount = 0; 1532 sii->ApcBypassCount = 0; 1533 sii++; 1534 } 1535 1536 return STATUS_SUCCESS; 1537 } 1538 1539 /* Class 24 - DPC Behaviour Information */ 1540 QSI_DEF(SystemDpcBehaviourInformation) 1541 { 1542 PSYSTEM_DPC_BEHAVIOR_INFORMATION sdbi = (PSYSTEM_DPC_BEHAVIOR_INFORMATION)Buffer; 1543 1544 if (Size < sizeof(SYSTEM_DPC_BEHAVIOR_INFORMATION)) 1545 { 1546 return STATUS_INFO_LENGTH_MISMATCH; 1547 } 1548 1549 sdbi->DpcQueueDepth = KiMaximumDpcQueueDepth; 1550 sdbi->MinimumDpcRate = KiMinimumDpcRate; 1551 sdbi->AdjustDpcThreshold = KiAdjustDpcThreshold; 1552 sdbi->IdealDpcRate = KiIdealDpcRate; 1553 1554 return STATUS_SUCCESS; 1555 } 1556 1557 SSI_DEF(SystemDpcBehaviourInformation) 1558 { 1559 /* FIXME */ 1560 DPRINT1("NtSetSystemInformation - SystemDpcBehaviourInformation not implemented\n"); 1561 return STATUS_NOT_IMPLEMENTED; 1562 } 1563 1564 /* Class 25 - Full Memory Information */ 1565 QSI_DEF(SystemFullMemoryInformation) 1566 { 1567 PULONG Spi = (PULONG) Buffer; 1568 1569 PEPROCESS TheIdleProcess; 1570 1571 *ReqSize = sizeof(ULONG); 1572 1573 if (sizeof(ULONG) != Size) 1574 { 1575 return STATUS_INFO_LENGTH_MISMATCH; 1576 } 1577 1578 DPRINT("SystemFullMemoryInformation\n"); 1579 1580 TheIdleProcess = PsIdleProcess; 1581 1582 DPRINT("PID: %p, KernelTime: %u PFFree: %lu PFUsed: %lu\n", 1583 TheIdleProcess->UniqueProcessId, 1584 TheIdleProcess->Pcb.KernelTime, 1585 MiFreeSwapPages, 1586 MiUsedSwapPages); 1587 1588 *Spi = MiMemoryConsumers[MC_USER].PagesUsed; 1589 1590 return STATUS_SUCCESS; 1591 } 1592 1593 /* Class 26 - Load Image */ 1594 SSI_DEF(SystemLoadGdiDriverInformation) 1595 { 1596 PSYSTEM_GDI_DRIVER_INFORMATION DriverInfo = (PVOID)Buffer; 1597 UNICODE_STRING ImageName; 1598 PVOID ImageBase; 1599 PVOID SectionPointer; 1600 ULONG_PTR EntryPoint; 1601 NTSTATUS Status; 1602 ULONG DirSize; 1603 PIMAGE_NT_HEADERS NtHeader; 1604 1605 /* Validate size */ 1606 if (Size != sizeof(SYSTEM_GDI_DRIVER_INFORMATION)) 1607 { 1608 /* Incorrect buffer length, fail */ 1609 return STATUS_INFO_LENGTH_MISMATCH; 1610 } 1611 1612 /* Only kernel mode can call this function */ 1613 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD; 1614 1615 /* Load the driver */ 1616 ImageName = DriverInfo->DriverName; 1617 Status = MmLoadSystemImage(&ImageName, 1618 NULL, 1619 NULL, 1620 0, 1621 &SectionPointer, 1622 &ImageBase); 1623 if (!NT_SUCCESS(Status)) return Status; 1624 1625 /* Return the export pointer */ 1626 DriverInfo->ExportSectionPointer = 1627 RtlImageDirectoryEntryToData(ImageBase, 1628 TRUE, 1629 IMAGE_DIRECTORY_ENTRY_EXPORT, 1630 &DirSize); 1631 1632 /* Get the entrypoint */ 1633 NtHeader = RtlImageNtHeader(ImageBase); 1634 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; 1635 EntryPoint += (ULONG_PTR)ImageBase; 1636 1637 /* Save other data */ 1638 DriverInfo->ImageAddress = ImageBase; 1639 DriverInfo->SectionPointer = SectionPointer; 1640 DriverInfo->EntryPoint = (PVOID)EntryPoint; 1641 DriverInfo->ImageLength = NtHeader->OptionalHeader.SizeOfImage; 1642 1643 /* All is good */ 1644 return STATUS_SUCCESS; 1645 } 1646 1647 /* Class 27 - Unload Image */ 1648 SSI_DEF(SystemUnloadGdiDriverInformation) 1649 { 1650 PVOID *SectionPointer = Buffer; 1651 1652 /* Validate size */ 1653 if (Size != sizeof(PVOID)) 1654 { 1655 /* Incorrect length, fail */ 1656 return STATUS_INFO_LENGTH_MISMATCH; 1657 } 1658 1659 /* Only kernel mode can call this function */ 1660 if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD; 1661 1662 /* Unload the image */ 1663 MmUnloadSystemImage(*SectionPointer); 1664 return STATUS_SUCCESS; 1665 } 1666 1667 /* Class 28 - Time Adjustment Information */ 1668 QSI_DEF(SystemTimeAdjustmentInformation) 1669 { 1670 PSYSTEM_QUERY_TIME_ADJUST_INFORMATION TimeInfo = 1671 (PSYSTEM_QUERY_TIME_ADJUST_INFORMATION)Buffer; 1672 1673 /* Check if enough storage was provided */ 1674 if (sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION) > Size) 1675 { 1676 * ReqSize = sizeof(SYSTEM_QUERY_TIME_ADJUST_INFORMATION); 1677 return STATUS_INFO_LENGTH_MISMATCH; 1678 } 1679 1680 /* Give time values to our caller */ 1681 TimeInfo->TimeIncrement = KeMaximumIncrement; 1682 TimeInfo->TimeAdjustment = KeTimeAdjustment; 1683 TimeInfo->Enable = !KiTimeAdjustmentEnabled; 1684 1685 return STATUS_SUCCESS; 1686 } 1687 1688 SSI_DEF(SystemTimeAdjustmentInformation) 1689 { 1690 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 1691 PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo = 1692 (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer; 1693 1694 /* Check size of a buffer, it must match our expectations */ 1695 if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size) 1696 return STATUS_INFO_LENGTH_MISMATCH; 1697 1698 /* Check who is calling */ 1699 if (PreviousMode != KernelMode) 1700 { 1701 /* Check access rights */ 1702 if (!SeSinglePrivilegeCheck(SeSystemtimePrivilege, PreviousMode)) 1703 { 1704 return STATUS_PRIVILEGE_NOT_HELD; 1705 } 1706 } 1707 1708 /* FIXME: behaviour suggests the member be named 'Disable' */ 1709 if (TimeInfo->Enable) 1710 { 1711 /* Disable time adjustment and set default value */ 1712 KiTimeAdjustmentEnabled = FALSE; 1713 KeTimeAdjustment = KeMaximumIncrement; 1714 } 1715 else 1716 { 1717 /* Check if a valid time adjustment value is given */ 1718 if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2; 1719 1720 /* Enable time adjustment and set the adjustment value */ 1721 KiTimeAdjustmentEnabled = TRUE; 1722 KeTimeAdjustment = TimeInfo->TimeAdjustment; 1723 } 1724 1725 return STATUS_SUCCESS; 1726 } 1727 1728 /* Class 29 - Summary Memory Information */ 1729 QSI_DEF(SystemSummaryMemoryInformation) 1730 { 1731 /* FIXME */ 1732 DPRINT1("NtQuerySystemInformation - SystemSummaryMemoryInformation not implemented\n"); 1733 return STATUS_NOT_IMPLEMENTED; 1734 } 1735 1736 /* Class 30 - Next Event Id Information */ 1737 QSI_DEF(SystemNextEventIdInformation) 1738 { 1739 /* FIXME */ 1740 DPRINT1("NtQuerySystemInformation - SystemNextEventIdInformation not implemented\n"); 1741 return STATUS_NOT_IMPLEMENTED; 1742 } 1743 1744 /* Class 31 */ 1745 QSI_DEF(SystemPerformanceTraceInformation) 1746 { 1747 /* FIXME */ 1748 DPRINT1("NtQuerySystemInformation - SystemPerformanceTraceInformation not implemented\n"); 1749 return STATUS_NOT_IMPLEMENTED; 1750 } 1751 1752 /* Class 32 - Crash Dump Information */ 1753 QSI_DEF(SystemCrashDumpInformation) 1754 { 1755 /* FIXME */ 1756 DPRINT1("NtQuerySystemInformation - SystemCrashDumpInformation not implemented\n"); 1757 return STATUS_NOT_IMPLEMENTED; 1758 } 1759 1760 /* Class 33 - Exception Information */ 1761 QSI_DEF(SystemExceptionInformation) 1762 { 1763 PSYSTEM_EXCEPTION_INFORMATION ExceptionInformation = 1764 (PSYSTEM_EXCEPTION_INFORMATION)Buffer; 1765 PKPRCB Prcb; 1766 ULONG AlignmentFixupCount = 0, ExceptionDispatchCount = 0; 1767 ULONG FloatingEmulationCount = 0, ByteWordEmulationCount = 0; 1768 CHAR i; 1769 1770 /* Check size of a buffer, it must match our expectations */ 1771 if (sizeof(SYSTEM_EXCEPTION_INFORMATION) != Size) 1772 return STATUS_INFO_LENGTH_MISMATCH; 1773 1774 /* Sum up exception count information from all processors */ 1775 for (i = 0; i < KeNumberProcessors; i++) 1776 { 1777 Prcb = KiProcessorBlock[i]; 1778 if (Prcb) 1779 { 1780 AlignmentFixupCount += Prcb->KeAlignmentFixupCount; 1781 ExceptionDispatchCount += Prcb->KeExceptionDispatchCount; 1782 #ifndef _M_ARM 1783 FloatingEmulationCount += Prcb->KeFloatingEmulationCount; 1784 #endif // _M_ARM 1785 } 1786 } 1787 1788 /* Save information in user's buffer */ 1789 ExceptionInformation->AlignmentFixupCount = AlignmentFixupCount; 1790 ExceptionInformation->ExceptionDispatchCount = ExceptionDispatchCount; 1791 ExceptionInformation->FloatingEmulationCount = FloatingEmulationCount; 1792 ExceptionInformation->ByteWordEmulationCount = ByteWordEmulationCount; 1793 1794 return STATUS_SUCCESS; 1795 } 1796 1797 /* Class 34 - Crash Dump State Information */ 1798 QSI_DEF(SystemCrashDumpStateInformation) 1799 { 1800 /* FIXME */ 1801 DPRINT1("NtQuerySystemInformation - SystemCrashDumpStateInformation not implemented\n"); 1802 return STATUS_NOT_IMPLEMENTED; 1803 } 1804 1805 /* Class 35 - Kernel Debugger Information */ 1806 QSI_DEF(SystemKernelDebuggerInformation) 1807 { 1808 PSYSTEM_KERNEL_DEBUGGER_INFORMATION skdi = (PSYSTEM_KERNEL_DEBUGGER_INFORMATION) Buffer; 1809 1810 #if (NTDDI_VERSION >= NTDDI_VISTA) 1811 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION); 1812 #endif 1813 1814 if (Size < sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION)) 1815 { 1816 return STATUS_INFO_LENGTH_MISMATCH; 1817 } 1818 1819 skdi->KernelDebuggerEnabled = KD_DEBUGGER_ENABLED; 1820 skdi->KernelDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT; 1821 1822 #if (NTDDI_VERSION < NTDDI_VISTA) 1823 *ReqSize = sizeof(SYSTEM_KERNEL_DEBUGGER_INFORMATION); 1824 #endif 1825 1826 return STATUS_SUCCESS; 1827 } 1828 1829 /* Class 36 - Context Switch Information */ 1830 QSI_DEF(SystemContextSwitchInformation) 1831 { 1832 PSYSTEM_CONTEXT_SWITCH_INFORMATION ContextSwitchInformation = 1833 (PSYSTEM_CONTEXT_SWITCH_INFORMATION)Buffer; 1834 ULONG ContextSwitches; 1835 PKPRCB Prcb; 1836 CHAR i; 1837 1838 /* Check size of a buffer, it must match our expectations */ 1839 if (sizeof(SYSTEM_CONTEXT_SWITCH_INFORMATION) != Size) 1840 return STATUS_INFO_LENGTH_MISMATCH; 1841 1842 /* Calculate total value of context switches across all processors */ 1843 ContextSwitches = 0; 1844 for (i = 0; i < KeNumberProcessors; i ++) 1845 { 1846 Prcb = KiProcessorBlock[i]; 1847 if (Prcb) 1848 { 1849 ContextSwitches += KeGetContextSwitches(Prcb); 1850 } 1851 } 1852 1853 ContextSwitchInformation->ContextSwitches = ContextSwitches; 1854 1855 /* FIXME */ 1856 ContextSwitchInformation->FindAny = 0; 1857 ContextSwitchInformation->FindLast = 0; 1858 ContextSwitchInformation->FindIdeal = 0; 1859 ContextSwitchInformation->IdleAny = 0; 1860 ContextSwitchInformation->IdleCurrent = 0; 1861 ContextSwitchInformation->IdleLast = 0; 1862 ContextSwitchInformation->IdleIdeal = 0; 1863 ContextSwitchInformation->PreemptAny = 0; 1864 ContextSwitchInformation->PreemptCurrent = 0; 1865 ContextSwitchInformation->PreemptLast = 0; 1866 ContextSwitchInformation->SwitchToIdle = 0; 1867 1868 return STATUS_SUCCESS; 1869 } 1870 1871 /* Class 37 - Registry Quota Information */ 1872 QSI_DEF(SystemRegistryQuotaInformation) 1873 { 1874 PSYSTEM_REGISTRY_QUOTA_INFORMATION srqi = (PSYSTEM_REGISTRY_QUOTA_INFORMATION) Buffer; 1875 1876 *ReqSize = sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION); 1877 if (Size < sizeof(SYSTEM_REGISTRY_QUOTA_INFORMATION)) 1878 { 1879 return STATUS_INFO_LENGTH_MISMATCH; 1880 } 1881 1882 DPRINT1("Faking max registry size of 32 MB\n"); 1883 srqi->RegistryQuotaAllowed = 0x2000000; 1884 srqi->RegistryQuotaUsed = 0x200000; 1885 srqi->PagedPoolSize = 0x200000; 1886 1887 return STATUS_SUCCESS; 1888 } 1889 1890 SSI_DEF(SystemRegistryQuotaInformation) 1891 { 1892 /* FIXME */ 1893 DPRINT1("NtSetSystemInformation - SystemRegistryQuotaInformation not implemented\n"); 1894 return STATUS_NOT_IMPLEMENTED; 1895 } 1896 1897 /* Class 38 - Load And Call Image */ 1898 SSI_DEF(SystemExtendServiceTableInformation) 1899 { 1900 UNICODE_STRING ImageName; 1901 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 1902 PLDR_DATA_TABLE_ENTRY ModuleObject; 1903 NTSTATUS Status; 1904 PIMAGE_NT_HEADERS NtHeader; 1905 DRIVER_OBJECT Win32k; 1906 PDRIVER_INITIALIZE DriverInit; 1907 PVOID ImageBase; 1908 ULONG_PTR EntryPoint; 1909 1910 /* Validate the size */ 1911 if (Size != sizeof(UNICODE_STRING)) return STATUS_INFO_LENGTH_MISMATCH; 1912 1913 /* Check who is calling */ 1914 if (PreviousMode != KernelMode) 1915 { 1916 static const UNICODE_STRING Win32kName = 1917 RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\win32k.sys"); 1918 1919 /* Make sure we can load drivers */ 1920 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, UserMode)) 1921 { 1922 /* FIXME: We can't, fail */ 1923 return STATUS_PRIVILEGE_NOT_HELD; 1924 } 1925 1926 _SEH2_TRY 1927 { 1928 /* Probe and copy the unicode string */ 1929 ProbeForRead(Buffer, sizeof(ImageName), 1); 1930 ImageName = *(PUNICODE_STRING)Buffer; 1931 1932 /* Probe the string buffer */ 1933 ProbeForRead(ImageName.Buffer, ImageName.Length, sizeof(WCHAR)); 1934 1935 /* Check if we have the correct name (nothing else is allowed!) */ 1936 if (!RtlEqualUnicodeString(&ImageName, &Win32kName, FALSE)) 1937 { 1938 _SEH2_YIELD(return STATUS_PRIVILEGE_NOT_HELD); 1939 } 1940 } 1941 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1942 { 1943 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 1944 } 1945 _SEH2_END; 1946 1947 /* Recursively call the function, so that we are from kernel mode */ 1948 return ZwSetSystemInformation(SystemExtendServiceTableInformation, 1949 (PVOID)&Win32kName, 1950 sizeof(Win32kName)); 1951 } 1952 1953 /* Load the image */ 1954 Status = MmLoadSystemImage((PUNICODE_STRING)Buffer, 1955 NULL, 1956 NULL, 1957 0, 1958 (PVOID)&ModuleObject, 1959 &ImageBase); 1960 1961 if (!NT_SUCCESS(Status)) return Status; 1962 1963 /* Get the headers */ 1964 NtHeader = RtlImageNtHeader(ImageBase); 1965 if (!NtHeader) 1966 { 1967 /* Fail */ 1968 MmUnloadSystemImage(ModuleObject); 1969 return STATUS_INVALID_IMAGE_FORMAT; 1970 } 1971 1972 /* Get the entrypoint */ 1973 EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; 1974 EntryPoint += (ULONG_PTR)ImageBase; 1975 DriverInit = (PDRIVER_INITIALIZE)EntryPoint; 1976 1977 /* Create a dummy device */ 1978 RtlZeroMemory(&Win32k, sizeof(Win32k)); 1979 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 1980 Win32k.DriverStart = ImageBase; 1981 1982 /* Call it */ 1983 Status = (DriverInit)(&Win32k, NULL); 1984 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); 1985 1986 /* Unload if we failed */ 1987 if (!NT_SUCCESS(Status)) MmUnloadSystemImage(ModuleObject); 1988 return Status; 1989 } 1990 1991 /* Class 39 - Priority Separation */ 1992 SSI_DEF(SystemPrioritySeperation) 1993 { 1994 /* Check if the size is correct */ 1995 if (Size != sizeof(ULONG)) 1996 { 1997 return STATUS_INFO_LENGTH_MISMATCH; 1998 } 1999 2000 /* We need the TCB privilege */ 2001 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, ExGetPreviousMode())) 2002 { 2003 return STATUS_PRIVILEGE_NOT_HELD; 2004 } 2005 2006 /* Modify the quantum table */ 2007 PsChangeQuantumTable(TRUE, *(PULONG)Buffer); 2008 2009 return STATUS_SUCCESS; 2010 } 2011 2012 /* Class 40 */ 2013 QSI_DEF(SystemVerifierAddDriverInformation) 2014 { 2015 /* FIXME */ 2016 DPRINT1("NtQuerySystemInformation - SystemVerifierAddDriverInformation not implemented\n"); 2017 return STATUS_NOT_IMPLEMENTED; 2018 } 2019 2020 /* Class 41 */ 2021 QSI_DEF(SystemVerifierRemoveDriverInformation) 2022 { 2023 /* FIXME */ 2024 DPRINT1("NtQuerySystemInformation - SystemVerifierRemoveDriverInformation not implemented\n"); 2025 return STATUS_NOT_IMPLEMENTED; 2026 } 2027 2028 /* Class 42 - Power Information */ 2029 QSI_DEF(SystemProcessorIdleInformation) 2030 { 2031 *ReqSize = sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors; 2032 2033 if (sizeof(PROCESSOR_POWER_INFORMATION) * KeNumberProcessors > Size) 2034 { 2035 return STATUS_INFO_LENGTH_MISMATCH; 2036 } 2037 2038 /* FIXME */ 2039 DPRINT1("NtQuerySystemInformation - SystemPowerInformation not implemented\n"); 2040 return STATUS_NOT_IMPLEMENTED; 2041 } 2042 2043 /* Class 43 */ 2044 QSI_DEF(SystemLegacyDriverInformation) 2045 { 2046 /* FIXME */ 2047 DPRINT1("NtQuerySystemInformation - SystemLegacyDriverInformation not implemented\n"); 2048 return STATUS_NOT_IMPLEMENTED; 2049 } 2050 2051 /* Class 44 - Current Time Zone Information */ 2052 QSI_DEF(SystemCurrentTimeZoneInformation) 2053 { 2054 *ReqSize = sizeof(RTL_TIME_ZONE_INFORMATION); 2055 2056 if (sizeof(RTL_TIME_ZONE_INFORMATION) != Size) 2057 { 2058 return STATUS_INFO_LENGTH_MISMATCH; 2059 } 2060 2061 /* Copy the time zone information struct */ 2062 memcpy(Buffer, 2063 &ExpTimeZoneInfo, 2064 sizeof(RTL_TIME_ZONE_INFORMATION)); 2065 2066 return STATUS_SUCCESS; 2067 } 2068 2069 2070 SSI_DEF(SystemCurrentTimeZoneInformation) 2071 { 2072 /* Check user buffer's size */ 2073 if (Size < sizeof(RTL_TIME_ZONE_INFORMATION)) 2074 { 2075 return STATUS_INFO_LENGTH_MISMATCH; 2076 } 2077 2078 return ExpSetTimeZoneInformation((PRTL_TIME_ZONE_INFORMATION)Buffer); 2079 } 2080 2081 static 2082 VOID 2083 ExpCopyLookasideInformation( 2084 PSYSTEM_LOOKASIDE_INFORMATION *InfoPointer, 2085 PULONG RemainingPointer, 2086 PLIST_ENTRY ListHead, 2087 BOOLEAN ListUsesMisses) 2088 2089 { 2090 PSYSTEM_LOOKASIDE_INFORMATION Info; 2091 PGENERAL_LOOKASIDE LookasideList; 2092 PLIST_ENTRY ListEntry; 2093 ULONG Remaining; 2094 2095 /* Get info pointer and remaining count of free array element */ 2096 Info = *InfoPointer; 2097 Remaining = *RemainingPointer; 2098 2099 /* Loop as long as we have lookaside lists and free array elements */ 2100 for (ListEntry = ListHead->Flink; 2101 (ListEntry != ListHead) && (Remaining > 0); 2102 ListEntry = ListEntry->Flink, Remaining--) 2103 { 2104 LookasideList = CONTAINING_RECORD(ListEntry, GENERAL_LOOKASIDE, ListEntry); 2105 2106 /* Fill the next array element */ 2107 Info->CurrentDepth = LookasideList->Depth; 2108 Info->MaximumDepth = LookasideList->MaximumDepth; 2109 Info->TotalAllocates = LookasideList->TotalAllocates; 2110 Info->TotalFrees = LookasideList->TotalFrees; 2111 Info->Type = LookasideList->Type; 2112 Info->Tag = LookasideList->Tag; 2113 Info->Size = LookasideList->Size; 2114 2115 /* Check how the lists track misses/hits */ 2116 if (ListUsesMisses) 2117 { 2118 /* Copy misses */ 2119 Info->AllocateMisses = LookasideList->AllocateMisses; 2120 Info->FreeMisses = LookasideList->FreeMisses; 2121 } 2122 else 2123 { 2124 /* Calculate misses */ 2125 Info->AllocateMisses = LookasideList->TotalAllocates 2126 - LookasideList->AllocateHits; 2127 Info->FreeMisses = LookasideList->TotalFrees 2128 - LookasideList->FreeHits; 2129 } 2130 } 2131 2132 /* Return the updated pointer and remaining count */ 2133 *InfoPointer = Info; 2134 *RemainingPointer = Remaining; 2135 } 2136 2137 /* Class 45 - Lookaside Information */ 2138 QSI_DEF(SystemLookasideInformation) 2139 { 2140 KPROCESSOR_MODE PreviousMode; 2141 PSYSTEM_LOOKASIDE_INFORMATION Info; 2142 PMDL Mdl; 2143 ULONG MaxCount, Remaining; 2144 KIRQL OldIrql; 2145 NTSTATUS Status; 2146 2147 /* First we need to lock down the memory, since we are going to access it 2148 at high IRQL */ 2149 PreviousMode = ExGetPreviousMode(); 2150 Status = ExLockUserBuffer(Buffer, 2151 Size, 2152 PreviousMode, 2153 IoWriteAccess, 2154 (PVOID*)&Info, 2155 &Mdl); 2156 if (!NT_SUCCESS(Status)) 2157 { 2158 DPRINT1("Failed to lock the user buffer: 0x%lx\n", Status); 2159 return Status; 2160 } 2161 2162 /* Calculate how many items we can store */ 2163 Remaining = MaxCount = Size / sizeof(SYSTEM_LOOKASIDE_INFORMATION); 2164 if (Remaining == 0) 2165 { 2166 goto Leave; 2167 } 2168 2169 /* Copy info from pool lookaside lists */ 2170 ExpCopyLookasideInformation(&Info, 2171 &Remaining, 2172 &ExPoolLookasideListHead, 2173 FALSE); 2174 if (Remaining == 0) 2175 { 2176 goto Leave; 2177 } 2178 2179 /* Copy info from system lookaside lists */ 2180 ExpCopyLookasideInformation(&Info, 2181 &Remaining, 2182 &ExSystemLookasideListHead, 2183 TRUE); 2184 if (Remaining == 0) 2185 { 2186 goto Leave; 2187 } 2188 2189 /* Acquire spinlock for ExpNonPagedLookasideListHead */ 2190 KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql); 2191 2192 /* Copy info from non-paged lookaside lists */ 2193 ExpCopyLookasideInformation(&Info, 2194 &Remaining, 2195 &ExpNonPagedLookasideListHead, 2196 TRUE); 2197 2198 /* Release spinlock for ExpNonPagedLookasideListHead */ 2199 KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); 2200 2201 if (Remaining == 0) 2202 { 2203 goto Leave; 2204 } 2205 2206 /* Acquire spinlock for ExpPagedLookasideListHead */ 2207 KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql); 2208 2209 /* Copy info from paged lookaside lists */ 2210 ExpCopyLookasideInformation(&Info, 2211 &Remaining, 2212 &ExpPagedLookasideListHead, 2213 TRUE); 2214 2215 /* Release spinlock for ExpPagedLookasideListHead */ 2216 KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); 2217 2218 Leave: 2219 2220 /* Release the locked user buffer */ 2221 ExUnlockUserBuffer(Mdl); 2222 2223 /* Return the size of the actually written data */ 2224 *ReqSize = (MaxCount - Remaining) * sizeof(SYSTEM_LOOKASIDE_INFORMATION); 2225 return STATUS_SUCCESS; 2226 } 2227 2228 2229 /* Class 46 - Set time slip event */ 2230 SSI_DEF(SystemTimeSlipNotification) 2231 { 2232 /* FIXME */ 2233 DPRINT1("NtSetSystemInformation - SystemTimeSlipNotification not implemented\n"); 2234 return STATUS_NOT_IMPLEMENTED; 2235 } 2236 2237 NTSTATUS 2238 NTAPI 2239 MmSessionCreate(OUT PULONG SessionId); 2240 2241 NTSTATUS 2242 NTAPI 2243 MmSessionDelete(IN ULONG SessionId); 2244 2245 /* Class 47 - Create a new session (TSE) */ 2246 SSI_DEF(SystemSessionCreate) 2247 { 2248 ULONG SessionId; 2249 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 2250 NTSTATUS Status; 2251 2252 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH; 2253 2254 if (PreviousMode != KernelMode) 2255 { 2256 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2257 { 2258 return STATUS_PRIVILEGE_NOT_HELD; 2259 } 2260 2261 ProbeForWriteUlong(Buffer); 2262 } 2263 2264 Status = MmSessionCreate(&SessionId); 2265 if (NT_SUCCESS(Status)) *(PULONG)Buffer = SessionId; 2266 2267 return Status; 2268 } 2269 2270 2271 /* Class 48 - Delete an existing session (TSE) */ 2272 SSI_DEF(SystemSessionDetach) 2273 { 2274 ULONG SessionId; 2275 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 2276 2277 if (Size != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH; 2278 2279 if (PreviousMode != KernelMode) 2280 { 2281 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2282 { 2283 return STATUS_PRIVILEGE_NOT_HELD; 2284 } 2285 } 2286 2287 SessionId = *(PULONG)Buffer; 2288 2289 return MmSessionDelete(SessionId); 2290 } 2291 2292 2293 /* Class 49 - UNKNOWN */ 2294 QSI_DEF(SystemSessionInformation) 2295 { 2296 /* FIXME */ 2297 DPRINT1("NtQuerySystemInformation - SystemSessionInformation not implemented\n"); 2298 return STATUS_NOT_IMPLEMENTED; 2299 } 2300 2301 2302 /* Class 50 - System range start address */ 2303 QSI_DEF(SystemRangeStartInformation) 2304 { 2305 /* Check user buffer's size */ 2306 if (Size != sizeof(ULONG_PTR)) return STATUS_INFO_LENGTH_MISMATCH; 2307 2308 *(PULONG_PTR)Buffer = (ULONG_PTR)MmSystemRangeStart; 2309 2310 if (ReqSize) *ReqSize = sizeof(ULONG_PTR); 2311 2312 return STATUS_SUCCESS; 2313 } 2314 2315 /* Class 51 - Driver verifier information */ 2316 QSI_DEF(SystemVerifierInformation) 2317 { 2318 /* FIXME */ 2319 DPRINT1("NtQuerySystemInformation - SystemVerifierInformation not implemented\n"); 2320 return STATUS_NOT_IMPLEMENTED; 2321 } 2322 2323 2324 SSI_DEF(SystemVerifierInformation) 2325 { 2326 /* FIXME */ 2327 DPRINT1("NtSetSystemInformation - SystemVerifierInformation not implemented\n"); 2328 return STATUS_NOT_IMPLEMENTED; 2329 } 2330 2331 2332 /* Class 52 */ 2333 SSI_DEF(SystemVerifierThunkExtend) 2334 { 2335 /* FIXME */ 2336 DPRINT1("NtSetSystemInformation - SystemVerifierThunkExtend not implemented\n"); 2337 return STATUS_NOT_IMPLEMENTED; 2338 } 2339 2340 2341 /* Class 53 - A session's processes */ 2342 QSI_DEF(SystemSessionProcessesInformation) 2343 { 2344 /* FIXME */ 2345 DPRINT1("NtQuerySystemInformation - SystemSessionProcessInformation not implemented\n"); 2346 return STATUS_NOT_IMPLEMENTED; 2347 } 2348 2349 2350 /* Class 54 - Load & map in system space */ 2351 SSI_DEF(SystemLoadGdiDriverInSystemSpaceInformation) 2352 { 2353 /* FIXME */ 2354 DPRINT1("NtSetSystemInformation - SystemLoadGdiDriverInSystemSpaceInformation not implemented\n"); 2355 return STATUS_NOT_IMPLEMENTED; 2356 } 2357 2358 2359 /* Class 55 - NUMA processor information */ 2360 QSI_DEF(SystemNumaProcessorMap) 2361 { 2362 ULONG MaxEntries, Node; 2363 PSYSTEM_NUMA_INFORMATION NumaInformation = (PSYSTEM_NUMA_INFORMATION)Buffer; 2364 2365 /* Validate input size */ 2366 if (Size < sizeof(ULONG)) 2367 { 2368 return STATUS_INFO_LENGTH_MISMATCH; 2369 } 2370 2371 /* Return highest node */ 2372 NumaInformation->HighestNodeNumber = KeNumberNodes - 1; 2373 2374 /* Compute how much entries we will be able to put in output structure */ 2375 MaxEntries = (Size - FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask)) / sizeof(ULONGLONG); 2376 /* Make sure we don't overflow KeNodeBlock */ 2377 if (MaxEntries > KeNumberNodes) 2378 { 2379 MaxEntries = KeNumberNodes; 2380 } 2381 2382 /* If we have entries to write, and room for it */ 2383 if (Size >= FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) && 2384 MaxEntries != 0) 2385 { 2386 /* Already set size we return */ 2387 *ReqSize = FIELD_OFFSET(SYSTEM_NUMA_INFORMATION, ActiveProcessorsAffinityMask) + 2388 MaxEntries * sizeof(ULONGLONG); 2389 2390 /* For each node, return processor mask */ 2391 for (Node = 0; Node < MaxEntries; ++Node) 2392 { 2393 NumaInformation->ActiveProcessorsAffinityMask[Node] = KeNodeBlock[Node]->ProcessorMask; 2394 } 2395 } 2396 else 2397 { 2398 /* We only returned highest node number */ 2399 *ReqSize = sizeof(ULONG); 2400 } 2401 2402 return STATUS_SUCCESS; 2403 } 2404 2405 2406 /* Class 56 - Prefetcher information */ 2407 QSI_DEF(SystemPrefetcherInformation) 2408 { 2409 /* FIXME */ 2410 DPRINT1("NtQuerySystemInformation - SystemPrefetcherInformation not implemented\n"); 2411 return STATUS_NOT_IMPLEMENTED; 2412 } 2413 2414 2415 /* Class 57 - Extended process information */ 2416 QSI_DEF(SystemExtendedProcessInformation) 2417 { 2418 /* FIXME */ 2419 DPRINT1("NtQuerySystemInformation - SystemExtendedProcessInformation not implemented\n"); 2420 return STATUS_NOT_IMPLEMENTED; 2421 } 2422 2423 2424 /* Class 58 - Recommended shared ata alignment */ 2425 QSI_DEF(SystemRecommendedSharedDataAlignment) 2426 { 2427 /* FIXME */ 2428 DPRINT1("NtQuerySystemInformation - SystemRecommendedSharedDataAlignment not implemented\n"); 2429 return STATUS_NOT_IMPLEMENTED; 2430 } 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), /* should be SI_XX */ 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 (sizeof(CallQS) / sizeof(CallQS[0])) 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 Length, 2933 _Out_opt_ PULONG UnsafeResultLength) 2934 { 2935 KPROCESSOR_MODE PreviousMode; 2936 ULONG ResultLength = 0; 2937 ULONG Alignment = TYPE_ALIGNMENT(ULONG); 2938 NTSTATUS FStatus = STATUS_NOT_IMPLEMENTED; 2939 2940 PAGED_CODE(); 2941 2942 PreviousMode = ExGetPreviousMode(); 2943 2944 _SEH2_TRY 2945 { 2946 #if (NTDDI_VERSION >= NTDDI_VISTA) 2947 /* 2948 * Check if 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, Length, Alignment); 2964 if (UnsafeResultLength != NULL) 2965 ProbeForWriteUlong(UnsafeResultLength); 2966 } 2967 2968 if (UnsafeResultLength) 2969 *UnsafeResultLength = 0; 2970 2971 #if (NTDDI_VERSION < NTDDI_VISTA) 2972 /* 2973 * Check if 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 (NULL != CallQS [SystemInformationClass].Query) 2983 { 2984 /* 2985 * Hand the request to a subhandler. 2986 */ 2987 FStatus = CallQS [SystemInformationClass].Query(SystemInformation, 2988 Length, 2989 &ResultLength); 2990 2991 /* Save the result length to the caller */ 2992 if (UnsafeResultLength) 2993 *UnsafeResultLength = ResultLength; 2994 } 2995 } 2996 _SEH2_EXCEPT(ExSystemExceptionFilter()) 2997 { 2998 FStatus = _SEH2_GetExceptionCode(); 2999 } 3000 _SEH2_END; 3001 3002 return FStatus; 3003 } 3004 3005 3006 NTSTATUS 3007 NTAPI 3008 NtSetSystemInformation (IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 3009 IN 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 3023 * possible unsafe arguments. 3024 */ 3025 if (PreviousMode != KernelMode) 3026 { 3027 ProbeForRead(SystemInformation, SystemInformationLength, sizeof(ULONG)); 3028 } 3029 3030 /* 3031 * Check the request is valid. 3032 */ 3033 if ((SystemInformationClass >= MIN_SYSTEM_INFO_CLASS) && 3034 (SystemInformationClass < MAX_SYSTEM_INFO_CLASS)) 3035 { 3036 if (NULL != CallQS [SystemInformationClass].Set) 3037 { 3038 /* 3039 * Hand the request to a subhandler. 3040 */ 3041 Status = CallQS [SystemInformationClass].Set(SystemInformation, 3042 SystemInformationLength); 3043 } 3044 } 3045 } 3046 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3047 { 3048 Status = _SEH2_GetExceptionCode(); 3049 } 3050 _SEH2_END; 3051 3052 return Status; 3053 } 3054 3055 ULONG 3056 NTAPI 3057 NtGetCurrentProcessorNumber(VOID) 3058 { 3059 /* Just use Ke */ 3060 return KeGetCurrentProcessorNumber(); 3061 } 3062 3063 #undef ExGetPreviousMode 3064 KPROCESSOR_MODE 3065 NTAPI 3066 ExGetPreviousMode(VOID) 3067 { 3068 /* Just use Ke */ 3069 return KeGetPreviousMode(); 3070 } 3071