aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/MemoryLock.cpp
blob: d1b3bcc3214203f9eba6575ac9e0a8ddeb6c8196 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// Windows/MemoryLock.cpp

#include "StdAfx.h"

#include "../../C/CpuArch.h"

#include "MemoryLock.h"

namespace NWindows {
namespace NSecurity {

#ifndef UNDER_CE

#ifdef _UNICODE
#define MY_FUNC_SELECT(f) :: f
#else
#define MY_FUNC_SELECT(f) my_ ## f
extern "C" {
typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);
typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges,
    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
}
#define GET_PROC_ADDR(fff, name) Func_ ## fff  my_ ## fff  = (Func_ ## fff)GetProcAddress(hModule, name)
#endif

bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
{
  bool res = false;

  #ifndef _UNICODE

  HMODULE hModule = ::LoadLibrary(TEXT("Advapi32.dll"));
  if (hModule == NULL)
    return false;
  
  GET_PROC_ADDR(OpenProcessToken, "OpenProcessToken");
  GET_PROC_ADDR(LookupPrivilegeValue, "LookupPrivilegeValueA");
  GET_PROC_ADDR(AdjustTokenPrivileges, "AdjustTokenPrivileges");
  
  if (my_OpenProcessToken &&
      my_AdjustTokenPrivileges &&
      my_LookupPrivilegeValue)
  
  #endif

  {
    HANDLE token;
    if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
    {
      TOKEN_PRIVILEGES tp;
      if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))
      {
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);
        if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))
          res = (GetLastError() == ERROR_SUCCESS);
      }
      ::CloseHandle(token);
    }
  }
    
  #ifndef _UNICODE

  ::FreeLibrary(hModule);
  
  #endif

  return res;
}



typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);

/*
  We suppose that Window 10 works incorrectly with "Large Pages" at:
    - Windows 10 1703 (15063)
    - Windows 10 1709 (16299)

    - Windows 10 1809 (17763) on some CPUs that have no 1 GB page support.
         We need more information about that new BUG in Windows.
*/

unsigned Get_LargePages_RiskLevel()
{
  OSVERSIONINFOEXW vi;
  HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
  if (!ntdll)
    return 0;
  Func_RtlGetVersion func = (Func_RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion");
  if (!func)
    return 0;
  func(&vi);
  if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
    return 0;
  if (vi.dwMajorVersion + vi.dwMinorVersion != 10)
    return 0;
  if (vi.dwBuildNumber <= 16299)
    return 1;

  #ifdef MY_CPU_X86_OR_AMD64
  if (!CPU_IsSupported_PageGB())
    return 1;
  #endif

  return 0;
}

#endif

}}