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