Reactos
at master 608 lines 17 kB view raw
1/* 2 * PROJECT: ReactOS Win32 Base API 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: System Information Functions 5 * COPYRIGHT: Emanuele Aliberti 6 * Christoph von Wittich 7 * Thomas Weidenmueller 8 * Gunnar Andre Dalsnes 9 * Stanislav Motylkov (x86corez@gmail.com) 10 * Mark Jansen (mark.jansen@reactos.org) 11 * Copyright 2023 Ratin Gao <ratin@knsoft.org> 12 */ 13 14/* INCLUDES *******************************************************************/ 15 16#include <k32.h> 17 18#define NDEBUG 19#include <debug.h> 20 21#define PV_NT351 0x00030033 22 23/* PRIVATE FUNCTIONS **********************************************************/ 24 25VOID 26WINAPI 27GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION BasicInfo, 28 IN PSYSTEM_PROCESSOR_INFORMATION ProcInfo, 29 OUT LPSYSTEM_INFO SystemInfo) 30{ 31 RtlZeroMemory(SystemInfo, sizeof (SYSTEM_INFO)); 32 SystemInfo->wProcessorArchitecture = ProcInfo->ProcessorArchitecture; 33 SystemInfo->wReserved = 0; 34 SystemInfo->dwPageSize = BasicInfo->PageSize; 35 SystemInfo->lpMinimumApplicationAddress = (PVOID)BasicInfo->MinimumUserModeAddress; 36 SystemInfo->lpMaximumApplicationAddress = (PVOID)BasicInfo->MaximumUserModeAddress; 37 SystemInfo->dwActiveProcessorMask = BasicInfo->ActiveProcessorsAffinityMask; 38 SystemInfo->dwNumberOfProcessors = BasicInfo->NumberOfProcessors; 39 SystemInfo->wProcessorLevel = ProcInfo->ProcessorLevel; 40 SystemInfo->wProcessorRevision = ProcInfo->ProcessorRevision; 41 SystemInfo->dwAllocationGranularity = BasicInfo->AllocationGranularity; 42 43 switch (ProcInfo->ProcessorArchitecture) 44 { 45 case PROCESSOR_ARCHITECTURE_INTEL: 46 switch (ProcInfo->ProcessorLevel) 47 { 48 case 3: 49 SystemInfo->dwProcessorType = PROCESSOR_INTEL_386; 50 break; 51 case 4: 52 SystemInfo->dwProcessorType = PROCESSOR_INTEL_486; 53 break; 54 default: 55 SystemInfo->dwProcessorType = PROCESSOR_INTEL_PENTIUM; 56 } 57 break; 58 59 case PROCESSOR_ARCHITECTURE_AMD64: 60 SystemInfo->dwProcessorType = PROCESSOR_AMD_X8664; 61 break; 62 63 case PROCESSOR_ARCHITECTURE_IA64: 64 SystemInfo->dwProcessorType = PROCESSOR_INTEL_IA64; 65 break; 66 67 default: 68 SystemInfo->dwProcessorType = 0; 69 break; 70 } 71 72 if (PV_NT351 > GetProcessVersion(0)) 73 { 74 SystemInfo->wProcessorLevel = 0; 75 SystemInfo->wProcessorRevision = 0; 76 } 77} 78 79static 80UINT 81BaseQuerySystemFirmware( 82 _In_ DWORD FirmwareTableProviderSignature, 83 _In_ DWORD FirmwareTableID, 84 _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer, 85 _In_ DWORD BufferSize, 86 _In_ SYSTEM_FIRMWARE_TABLE_ACTION Action) 87{ 88 SYSTEM_FIRMWARE_TABLE_INFORMATION* SysFirmwareInfo; 89 ULONG Result = 0, ReturnedSize; 90 ULONG TotalSize = BufferSize + sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION); 91 NTSTATUS Status; 92 93 SysFirmwareInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TotalSize); 94 if (!SysFirmwareInfo) 95 { 96 SetLastError(ERROR_INVALID_PARAMETER); 97 return 0; 98 } 99 _SEH2_TRY 100 { 101 SysFirmwareInfo->ProviderSignature = FirmwareTableProviderSignature; 102 SysFirmwareInfo->TableID = FirmwareTableID; 103 SysFirmwareInfo->Action = Action; 104 SysFirmwareInfo->TableBufferLength = BufferSize; 105 106 Status = NtQuerySystemInformation(SystemFirmwareTableInformation, SysFirmwareInfo, TotalSize, &ReturnedSize); 107 108 if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) 109 Result = SysFirmwareInfo->TableBufferLength; 110 111 if (NT_SUCCESS(Status) && pFirmwareTableBuffer) 112 { 113 RtlCopyMemory(pFirmwareTableBuffer, SysFirmwareInfo->TableBuffer, SysFirmwareInfo->TableBufferLength); 114 } 115 } 116 _SEH2_FINALLY 117 { 118 RtlFreeHeap(RtlGetProcessHeap(), 0, SysFirmwareInfo); 119 } 120 _SEH2_END; 121 122 BaseSetLastNTError(Status); 123 return Result; 124} 125 126/* PUBLIC FUNCTIONS ***********************************************************/ 127 128/* 129 * @implemented 130 */ 131SIZE_T 132WINAPI 133GetLargePageMinimum(VOID) 134{ 135 return SharedUserData->LargePageMinimum; 136} 137 138/* 139 * @implemented 140 */ 141VOID 142WINAPI 143GetSystemInfo(IN LPSYSTEM_INFO lpSystemInfo) 144{ 145 SYSTEM_BASIC_INFORMATION BasicInfo; 146 SYSTEM_PROCESSOR_INFORMATION ProcInfo; 147 NTSTATUS Status; 148 149 Status = NtQuerySystemInformation(SystemBasicInformation, 150 &BasicInfo, 151 sizeof(BasicInfo), 152 0); 153 if (!NT_SUCCESS(Status)) return; 154 155 Status = NtQuerySystemInformation(SystemProcessorInformation, 156 &ProcInfo, 157 sizeof(ProcInfo), 158 0); 159 if (!NT_SUCCESS(Status)) return; 160 161 GetSystemInfoInternal(&BasicInfo, &ProcInfo, lpSystemInfo); 162} 163 164/* 165 * @implemented 166 */ 167BOOL 168WINAPI 169IsProcessorFeaturePresent(IN DWORD ProcessorFeature) 170{ 171 if (ProcessorFeature >= PROCESSOR_FEATURE_MAX) return FALSE; 172 return ((BOOL)SharedUserData->ProcessorFeatures[ProcessorFeature]); 173} 174 175/* 176 * @implemented 177 */ 178BOOL 179WINAPI 180GetSystemRegistryQuota(OUT PDWORD pdwQuotaAllowed, 181 OUT PDWORD pdwQuotaUsed) 182{ 183 SYSTEM_REGISTRY_QUOTA_INFORMATION QuotaInfo; 184 ULONG BytesWritten; 185 NTSTATUS Status; 186 187 Status = NtQuerySystemInformation(SystemRegistryQuotaInformation, 188 &QuotaInfo, 189 sizeof(QuotaInfo), 190 &BytesWritten); 191 if (NT_SUCCESS(Status)) 192 { 193 if (pdwQuotaAllowed) *pdwQuotaAllowed = QuotaInfo.RegistryQuotaAllowed; 194 if (pdwQuotaUsed) *pdwQuotaUsed = QuotaInfo.RegistryQuotaUsed; 195 return TRUE; 196 } 197 198 BaseSetLastNTError(Status); 199 return FALSE; 200} 201 202/* 203 * @implemented 204 */ 205VOID 206WINAPI 207GetNativeSystemInfo(IN LPSYSTEM_INFO lpSystemInfo) 208{ 209 SYSTEM_BASIC_INFORMATION BasicInfo; 210 SYSTEM_PROCESSOR_INFORMATION ProcInfo; 211 NTSTATUS Status; 212 213 Status = RtlGetNativeSystemInformation(SystemBasicInformation, 214 &BasicInfo, 215 sizeof(BasicInfo), 216 0); 217 if (!NT_SUCCESS(Status)) return; 218 219 Status = RtlGetNativeSystemInformation(SystemProcessorInformation, 220 &ProcInfo, 221 sizeof(ProcInfo), 222 0); 223 if (!NT_SUCCESS(Status)) return; 224 225 GetSystemInfoInternal(&BasicInfo, &ProcInfo, lpSystemInfo); 226} 227 228/* 229 * @implemented 230 */ 231BOOL 232WINAPI 233GetLogicalProcessorInformation(OUT PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, 234 IN OUT PDWORD ReturnLength) 235{ 236 NTSTATUS Status; 237 238 if (!ReturnLength) 239 { 240 SetLastError(ERROR_INVALID_PARAMETER); 241 return FALSE; 242 } 243 244 Status = NtQuerySystemInformation(SystemLogicalProcessorInformation, 245 Buffer, 246 *ReturnLength, 247 ReturnLength); 248 249 /* Normalize the error to what Win32 expects */ 250 if (Status == STATUS_INFO_LENGTH_MISMATCH) Status = STATUS_BUFFER_TOO_SMALL; 251 if (!NT_SUCCESS(Status)) 252 { 253 BaseSetLastNTError(Status); 254 return FALSE; 255 } 256 257 return TRUE; 258} 259 260/* 261 * @implemented 262 */ 263BOOL 264WINAPI 265GetNumaHighestNodeNumber(OUT PULONG HighestNodeNumber) 266{ 267 NTSTATUS Status; 268 ULONG Length; 269 ULONG PartialInfo[2]; // First two members of SYSTEM_NUMA_INFORMATION 270 271 /* Query partial NUMA info */ 272 Status = NtQuerySystemInformation(SystemNumaProcessorMap, 273 PartialInfo, 274 sizeof(PartialInfo), 275 &Length); 276 if (!NT_SUCCESS(Status)) 277 { 278 BaseSetLastNTError(Status); 279 return FALSE; 280 } 281 282 if (Length < sizeof(ULONG)) 283 { 284 SetLastError(ERROR_INVALID_PARAMETER); 285 return FALSE; 286 } 287 288 /* First member of the struct is the highest node number */ 289 *HighestNodeNumber = PartialInfo[0]; 290 return TRUE; 291} 292 293/* 294 * @implemented 295 */ 296BOOL 297WINAPI 298GetNumaNodeProcessorMask(IN UCHAR Node, 299 OUT PULONGLONG ProcessorMask) 300{ 301 NTSTATUS Status; 302 SYSTEM_NUMA_INFORMATION NumaInformation; 303 ULONG Length; 304 305 /* Query NUMA information */ 306 Status = NtQuerySystemInformation(SystemNumaProcessorMap, 307 &NumaInformation, 308 sizeof(NumaInformation), 309 &Length); 310 if (!NT_SUCCESS(Status)) 311 { 312 BaseSetLastNTError(Status); 313 return FALSE; 314 } 315 316 /* Validate input node number */ 317 if (Node > NumaInformation.HighestNodeNumber) 318 { 319 SetLastError(ERROR_INVALID_PARAMETER); 320 return FALSE; 321 } 322 323 /* Return mask for that node */ 324 *ProcessorMask = NumaInformation.ActiveProcessorsAffinityMask[Node]; 325 return TRUE; 326} 327 328/* 329 * @implemented 330 */ 331BOOL 332WINAPI 333GetNumaProcessorNode(IN UCHAR Processor, 334 OUT PUCHAR NodeNumber) 335{ 336 NTSTATUS Status; 337 SYSTEM_NUMA_INFORMATION NumaInformation; 338 ULONG Length; 339 ULONG Node; 340 ULONGLONG Proc; 341 342 /* Can't handle processor number >= 32 */ 343 if (Processor >= MAXIMUM_PROCESSORS) 344 { 345 *NodeNumber = -1; 346 SetLastError(ERROR_INVALID_PARAMETER); 347 return FALSE; 348 } 349 350 /* Query NUMA information */ 351 Status = NtQuerySystemInformation(SystemNumaProcessorMap, 352 &NumaInformation, 353 sizeof(NumaInformation), 354 &Length); 355 if (!NT_SUCCESS(Status)) 356 { 357 *NodeNumber = -1; 358 BaseSetLastNTError(Status); 359 return FALSE; 360 } 361 362 /* Find ourselves */ 363 Node = 0; 364 Proc = 1ULL << Processor; 365 while ((Proc & NumaInformation.ActiveProcessorsAffinityMask[Node]) == 0ULL) 366 { 367 ++Node; 368 /* Out of options */ 369 if (Node > NumaInformation.HighestNodeNumber) 370 { 371 *NodeNumber = -1; 372 SetLastError(ERROR_INVALID_PARAMETER); 373 return FALSE; 374 } 375 } 376 377 /* Return found node */ 378 *NodeNumber = Node; 379 return TRUE; 380} 381 382/* 383 * @implemented 384 */ 385BOOL 386WINAPI 387GetNumaAvailableMemoryNode(IN UCHAR Node, 388 OUT PULONGLONG AvailableBytes) 389{ 390 NTSTATUS Status; 391 SYSTEM_NUMA_INFORMATION NumaInformation; 392 ULONG Length; 393 394 /* Query NUMA information */ 395 Status = NtQuerySystemInformation(SystemNumaAvailableMemory, 396 &NumaInformation, 397 sizeof(NumaInformation), 398 &Length); 399 if (!NT_SUCCESS(Status)) 400 { 401 BaseSetLastNTError(Status); 402 return FALSE; 403 } 404 405 /* Validate input node number */ 406 if (Node > NumaInformation.HighestNodeNumber) 407 { 408 SetLastError(ERROR_INVALID_PARAMETER); 409 return FALSE; 410 } 411 412 /* Return available memory for that node */ 413 *AvailableBytes = NumaInformation.AvailableMemory[Node]; 414 return TRUE; 415} 416 417_Success_(return > 0) 418DWORD 419WINAPI 420GetFirmwareEnvironmentVariableExW( 421 _In_ LPCWSTR lpName, 422 _In_ LPCWSTR lpGuid, 423 _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer, 424 _In_ DWORD nSize, 425 _Out_opt_ PDWORD pdwAttribubutes); 426 427_Success_(return > 0) 428DWORD 429WINAPI 430GetFirmwareEnvironmentVariableExA( 431 _In_ LPCSTR lpName, 432 _In_ LPCSTR lpGuid, 433 _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer, 434 _In_ DWORD nSize, 435 _Out_opt_ PDWORD pdwAttribubutes); 436 437BOOL 438WINAPI 439SetFirmwareEnvironmentVariableExW( 440 _In_ LPCWSTR lpName, 441 _In_ LPCWSTR lpGuid, 442 _In_reads_bytes_opt_(nSize) PVOID pValue, 443 _In_ DWORD nSize, 444 _In_ DWORD dwAttributes); 445 446BOOL 447WINAPI 448SetFirmwareEnvironmentVariableExA( 449 _In_ LPCSTR lpName, 450 _In_ LPCSTR lpGuid, 451 _In_reads_bytes_opt_(nSize) PVOID pValue, 452 _In_ DWORD nSize, 453 _In_ DWORD dwAttributes); 454 455_Success_(return > 0) 456DWORD 457WINAPI 458GetFirmwareEnvironmentVariableW( 459 _In_ LPCWSTR lpName, 460 _In_ LPCWSTR lpGuid, 461 _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer, 462 _In_ DWORD nSize) 463{ 464 return GetFirmwareEnvironmentVariableExW(lpName, lpGuid, pBuffer, nSize, NULL); 465} 466 467BOOL 468WINAPI 469SetFirmwareEnvironmentVariableW( 470 _In_ LPCWSTR lpName, 471 _In_ LPCWSTR lpGuid, 472 _In_reads_bytes_opt_(nSize) PVOID pValue, 473 _In_ DWORD nSize) 474{ 475 return SetFirmwareEnvironmentVariableExW(lpName, 476 lpGuid, 477 pValue, 478 nSize, 479 VARIABLE_ATTRIBUTE_NON_VOLATILE); 480} 481 482/** 483 * @name EnumSystemFirmwareTables 484 * @implemented 485 * 486 * Obtains firmware table identifiers. 487 * https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-enumsystemfirmwaretables 488 * 489 * @param FirmwareTableProviderSignature 490 * Can be either ACPI, FIRM, or RSMB. 491 * 492 * @param pFirmwareTableBuffer 493 * Pointer to the output buffer, can be NULL. 494 * 495 * @param BufferSize 496 * Size of the output buffer. 497 * 498 * @return 499 * Actual size of the data in case of success, 0 otherwise. 500 * 501 * @remarks 502 * Data would be written to buffer only if the specified size is 503 * larger or equal to the actual size, in the other case Last Error 504 * value would be set to ERROR_INSUFFICIENT_BUFFER. 505 * In case of incorrect provider signature, Last Error value would be 506 * set to ERROR_INVALID_FUNCTION. 507 * 508 */ 509UINT 510WINAPI 511EnumSystemFirmwareTables( 512 _In_ DWORD FirmwareTableProviderSignature, 513 _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableEnumBuffer, 514 _In_ DWORD BufferSize) 515{ 516 return BaseQuerySystemFirmware(FirmwareTableProviderSignature, 517 0, 518 pFirmwareTableEnumBuffer, 519 BufferSize, 520 SystemFirmwareTable_Enumerate); 521} 522 523/** 524 * @name GetSystemFirmwareTable 525 * @implemented 526 * 527 * Obtains the firmware table data. 528 * https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemfirmwaretable 529 * 530 * @param FirmwareTableProviderSignature 531 * Can be either ACPI, FIRM, or RSMB. 532 * 533 * @param FirmwareTableID 534 * Correct table identifier. 535 * 536 * @param pFirmwareTableBuffer 537 * Pointer to the output buffer, can be NULL. 538 * 539 * @param BufferSize 540 * Size of the output buffer. 541 * 542 * @return 543 * Actual size of the data in case of success, 0 otherwise. 544 * 545 * @remarks 546 * Data would be written to buffer only if the specified size is 547 * larger or equal to the actual size, in the other case Last Error 548 * value would be set to ERROR_INSUFFICIENT_BUFFER. 549 * In case of incorrect provider signature, Last Error value would be 550 * set to ERROR_INVALID_FUNCTION. 551 * Also Last Error value becomes ERROR_NOT_FOUND if incorrect 552 * table identifier was specified along with ACPI provider, and 553 * ERROR_INVALID_PARAMETER along with FIRM provider. The RSMB provider 554 * accepts any table identifier. 555 * 556 */ 557UINT 558WINAPI 559GetSystemFirmwareTable( 560 _In_ DWORD FirmwareTableProviderSignature, 561 _In_ DWORD FirmwareTableID, 562 _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer, 563 _In_ DWORD BufferSize) 564{ 565 return BaseQuerySystemFirmware(FirmwareTableProviderSignature, 566 FirmwareTableID, 567 pFirmwareTableBuffer, 568 BufferSize, 569 SystemFirmwareTable_Get); 570} 571 572/* 573 * @unimplemented 574 */ 575BOOL 576WINAPI 577GetSystemFileCacheSize(OUT PSIZE_T lpMinimumFileCacheSize, 578 OUT PSIZE_T lpMaximumFileCacheSize, 579 OUT PDWORD lpFlags) 580{ 581 STUB; 582 return FALSE; 583} 584 585/* 586 * @unimplemented 587 */ 588BOOL 589WINAPI 590SetSystemFileCacheSize(IN SIZE_T MinimumFileCacheSize, 591 IN SIZE_T MaximumFileCacheSize, 592 IN DWORD Flags) 593{ 594 STUB; 595 return FALSE; 596} 597 598/* 599 * @unimplemented 600 */ 601LONG 602WINAPI 603GetCurrentPackageId(UINT32 *BufferLength, 604 BYTE *Buffer) 605{ 606 STUB; 607 return APPMODEL_ERROR_NO_PACKAGE; 608}