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