From 41a9dfefb68fb2337a250c97c3c24b28d8ab686f Mon Sep 17 00:00:00 2001
From: Brad King <brad.king@kitware.com>
Date: Wed, 29 Mar 2017 16:44:21 -0400
Subject: [PATCH] SystemInformation: Fix dynamic loader failure on WinXP SP2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Load the `GetLogicalProcessorInformation` function address at runtime.
If it is not available use a fallback implementation.

Co-Author: Nicolás Bértolo <nicolasbertolo@gmail.com>
Issue: cmake/cmake#16751
---
 SystemInformation.cxx | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/SystemInformation.cxx b/SystemInformation.cxx
index 93312e9d..70f1a434 100644
--- a/SystemInformation.cxx
+++ b/SystemInformation.cxx
@@ -4341,18 +4341,35 @@ unsigned char SystemInformationImplementation::GetAPICId()
 void SystemInformationImplementation::CPUCountWindows()
 {
 #if defined(_WIN32)
-  std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
   this->NumberOfPhysicalCPU = 0;
   this->NumberOfLogicalCPU = 0;
 
+  typedef BOOL(WINAPI * GetLogicalProcessorInformationType)(
+    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+  static GetLogicalProcessorInformationType pGetLogicalProcessorInformation =
+    (GetLogicalProcessorInformationType)GetProcAddress(
+      GetModuleHandleW(L"kernel32"), "GetLogicalProcessorInformation");
+
+  if (!pGetLogicalProcessorInformation) {
+    // Fallback to approximate implementation on ancient Windows versions.
+    SYSTEM_INFO info;
+    ZeroMemory(&info, sizeof(info));
+    GetSystemInfo(&info);
+    this->NumberOfPhysicalCPU =
+      static_cast<unsigned int>(info.dwNumberOfProcessors);
+    this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
+    return;
+  }
+
+  std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> ProcInfo;
   {
     DWORD Length = 0;
-    DWORD rc = GetLogicalProcessorInformation(NULL, &Length);
+    DWORD rc = pGetLogicalProcessorInformation(NULL, &Length);
     assert(FALSE == rc);
     (void)rc; // Silence unused variable warning in Borland C++ 5.81
     assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
     ProcInfo.resize(Length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
-    rc = GetLogicalProcessorInformation(&ProcInfo[0], &Length);
+    rc = pGetLogicalProcessorInformation(&ProcInfo[0], &Length);
     assert(rc != FALSE);
     (void)rc; // Silence unused variable warning in Borland C++ 5.81
   }
-- 
GitLab