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