xref: /third_party/lzma/CPP/Windows/MemoryLock.cpp (revision 370b324c)
1// Windows/MemoryLock.cpp
2
3#include "StdAfx.h"
4
5#include "../../C/CpuArch.h"
6
7#include "MemoryLock.h"
8
9namespace NWindows {
10namespace NSecurity {
11
12#ifndef UNDER_CE
13
14#ifdef _UNICODE
15#define MY_FUNC_SELECT(f) :: f
16#else
17#define MY_FUNC_SELECT(f) my_ ## f
18extern "C" {
19typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
20typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);
21typedef BOOL (WINAPI * Func_AdjustTokenPrivileges)(HANDLE TokenHandle, BOOL DisableAllPrivileges,
22    PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength);
23}
24
25#define GET_PROC_ADDR(fff, name)  \
26  const Func_ ## fff  my_ ## fff = Z7_GET_PROC_ADDRESS( \
27        Func_ ## fff, hModule, name);
28#endif
29
30bool EnablePrivilege(LPCTSTR privilegeName, bool enable)
31{
32  bool res = false;
33
34  #ifndef _UNICODE
35
36  const HMODULE hModule = ::LoadLibrary(TEXT("advapi32.dll"));
37  if (!hModule)
38    return false;
39
40  GET_PROC_ADDR(
41     OpenProcessToken,
42    "OpenProcessToken")
43  GET_PROC_ADDR(
44     LookupPrivilegeValue,
45    "LookupPrivilegeValueA")
46  GET_PROC_ADDR(
47     AdjustTokenPrivileges,
48    "AdjustTokenPrivileges")
49
50  if (my_OpenProcessToken &&
51      my_AdjustTokenPrivileges &&
52      my_LookupPrivilegeValue)
53
54  #endif
55
56  {
57    HANDLE token;
58    if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
59    {
60      TOKEN_PRIVILEGES tp;
61      if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))
62      {
63        tp.PrivilegeCount = 1;
64        tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);
65        if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))
66          res = (GetLastError() == ERROR_SUCCESS);
67      }
68      ::CloseHandle(token);
69    }
70  }
71
72  #ifndef _UNICODE
73
74  ::FreeLibrary(hModule);
75
76  #endif
77
78  return res;
79}
80
81
82
83typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
84
85/*
86  We suppose that Window 10 works incorrectly with "Large Pages" at:
87    - Windows 10 1703 (15063) : incorrect allocating after VirtualFree()
88    - Windows 10 1709 (16299) : incorrect allocating after VirtualFree()
89    - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger,
90                                if CPU doesn't support 1 GB pages.
91  Windows 10 1903 (18362) probably works correctly.
92*/
93
94unsigned Get_LargePages_RiskLevel()
95{
96  OSVERSIONINFOEXW vi;
97  const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
98  if (!ntdll)
99    return 0;
100  const
101  Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS(
102  Func_RtlGetVersion, ntdll,
103      "RtlGetVersion");
104  if (!func)
105    return 0;
106  func(&vi);
107  if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
108    return 0;
109  if (vi.dwMajorVersion + vi.dwMinorVersion != 10)
110    return 0;
111  if (vi.dwBuildNumber <= 16299)
112    return 1;
113
114  #ifdef MY_CPU_X86_OR_AMD64
115  if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB())
116    return 1;
117  #endif
118
119  return 0;
120}
121
122#endif
123
124}}
125