text: /* PopRig
   * Copyright 2010      Jeff Garzik <jgarzik@pobox.com>
   * Copyright 2012-2014 pooler      <pooler@litecoinpool.org>
   * Copyright 2014      Lucas Jones <https://github.com/lucasjones>
   * Copyright 2014-2016 Wolf9466    <https://github.com/OhGodAPet>
   * Copyright 2016      Jay D Dee   <jayddee246@gmail.com>
   * Copyright 2016-2017 XMRig       <support@xmrig.com>
   * Copyright 2018      PopRig    <https://github.com/PopchainOrg/poprig>
   *
   *
   *   This program is free software: you can redistribute it and/or modify
   *   it under the terms of the GNU General Public License as published by
   *   the Free Software Foundation, either version 3 of the License, or
   *   (at your option) any later version.
   *
   *   This program is distributed in the hope that it will be useful,
   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   *   GNU General Public License for more details.
   *
   *   You should have received a copy of the GNU General Public License
   *   along with this program. If not, see <http://www.gnu.org/licenses/>.
   */
  
  
  #include <winsock2.h>
  #include <windows.h>
  #include <uv.h>
  
  
  #include "Platform.h"
  #include "version.h"
  
  #ifdef POPRIG_NVIDIA_PROJECT
  #   include "nvidia/cryptopop.h"
  #endif
  
  
  static inline OSVERSIONINFOEX winOsVersion()
  {
      typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
      OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
  
      HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
      if (ntdll ) {
          RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll, "RtlGetVersion"));
  
          if (pRtlGetVersion) {
              pRtlGetVersion((LPOSVERSIONINFO) &result);
          }
      }
  
      return result;
  }
  
  
  static inline char *createUserAgent()
  {
      const auto osver = winOsVersion();
      const size_t max = 160;
  
      char *buf = new char[max];
      int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
  
  #   if defined(__x86_64__) || defined(_M_AMD64)
      length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string());
  #   else
      length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
  #   endif
  
  #   ifdef POPRIG_NVIDIA_PROJECT
      const int cudaVersion = cuda_get_runtime_version();
      length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
  #   endif
  
  #   ifdef __GNUC__
      length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
  #   elif _MSC_VER
      length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);
  #   endif
  
      return buf;
  }
  
  
  void Platform::init(const char *userAgent)
  {
      m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
  }
  
  
  void Platform::release()
  {
      delete [] m_defaultConfigName;
      delete [] m_userAgent;
  }
  
  
  void Platform::setProcessPriority(int priority)
  {
      if (priority == -1) {
          return;
      }
  
      DWORD prio = IDLE_PRIORITY_CLASS;
      switch (priority)
      {
      case 1:
          prio = BELOW_NORMAL_PRIORITY_CLASS;
          break;
  
      case 2:
          prio = NORMAL_PRIORITY_CLASS;
          break;
  
      case 3:
          prio = ABOVE_NORMAL_PRIORITY_CLASS;
          break;
  
      case 4:
          prio = HIGH_PRIORITY_CLASS;
          break;
  
      case 5:
          prio = REALTIME_PRIORITY_CLASS;
  
      default:
          break;
      }
  
      SetPriorityClass(GetCurrentProcess(), prio);
  }
  
  
  
  void Platform::setThreadPriority(int priority)
  {
      if (priority == -1) {
          return;
      }
  
      int prio = THREAD_PRIORITY_IDLE;
      switch (priority)
      {
      case 1:
          prio = THREAD_PRIORITY_BELOW_NORMAL;
          break;
  
      case 2:
          prio = THREAD_PRIORITY_NORMAL;
          break;
  
      case 3:
          prio = THREAD_PRIORITY_ABOVE_NORMAL;
          break;
  
      case 4:
          prio = THREAD_PRIORITY_HIGHEST;
          break;
  
      case 5:
          prio = THREAD_PRIORITY_TIME_CRITICAL;
          break;
  
      default:
          break;
      }
  
      SetThreadPriority(GetCurrentThread(), prio);
  }
  
  