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