1 // Windows/MemoryLock.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../C/CpuArch.h"
6
7 #include "MemoryLock.h"
8
9 namespace NWindows {
10 namespace 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
18 extern "C" {
19 typedef BOOL (WINAPI * Func_OpenProcessToken)(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle);
20 typedef BOOL (WINAPI * Func_LookupPrivilegeValue)(LPCTSTR lpSystemName, LPCTSTR lpName, PLUID lpLuid);
21 typedef 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
EnablePrivilege(LPCTSTR privilegeName,bool enable)30 bool 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 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
41
42 GET_PROC_ADDR(
43 OpenProcessToken,
44 "OpenProcessToken")
45 GET_PROC_ADDR(
46 LookupPrivilegeValue,
47 "LookupPrivilegeValueA")
48 GET_PROC_ADDR(
49 AdjustTokenPrivileges,
50 "AdjustTokenPrivileges")
51
52 if (my_OpenProcessToken &&
53 my_AdjustTokenPrivileges &&
54 my_LookupPrivilegeValue)
55
56 #endif
57
58 {
59 HANDLE token;
60 if (MY_FUNC_SELECT(OpenProcessToken)(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
61 {
62 TOKEN_PRIVILEGES tp;
63 if (MY_FUNC_SELECT(LookupPrivilegeValue)(NULL, privilegeName, &(tp.Privileges[0].Luid)))
64 {
65 tp.PrivilegeCount = 1;
66 tp.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0);
67 if (MY_FUNC_SELECT(AdjustTokenPrivileges)(token, FALSE, &tp, 0, NULL, NULL))
68 res = (GetLastError() == ERROR_SUCCESS);
69 }
70 ::CloseHandle(token);
71 }
72 }
73
74 #ifndef _UNICODE
75
76 ::FreeLibrary(hModule);
77
78 #endif
79
80 return res;
81 }
82
83
84 Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
85
86 typedef void (WINAPI * Func_RtlGetVersion) (OSVERSIONINFOEXW *);
87
88 /*
89 We suppose that Window 10 works incorrectly with "Large Pages" at:
90 - Windows 10 1703 (15063) : incorrect allocating after VirtualFree()
91 - Windows 10 1709 (16299) : incorrect allocating after VirtualFree()
92 - Windows 10 1809 (17763) : the failures for blocks of 1 GiB and larger,
93 if CPU doesn't support 1 GB pages.
94 Windows 10 1903 (18362) probably works correctly.
95 */
96
Get_LargePages_RiskLevel()97 unsigned Get_LargePages_RiskLevel()
98 {
99 OSVERSIONINFOEXW vi;
100 const HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
101 if (!ntdll)
102 return 0;
103 const
104 Func_RtlGetVersion func = Z7_GET_PROC_ADDRESS(
105 Func_RtlGetVersion, ntdll,
106 "RtlGetVersion");
107 if (!func)
108 return 0;
109 func(&vi);
110 if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT)
111 return 0;
112 if (vi.dwMajorVersion + vi.dwMinorVersion != 10)
113 return 0;
114 if (vi.dwBuildNumber <= 16299)
115 return 1;
116
117 #ifdef MY_CPU_X86_OR_AMD64
118 if (vi.dwBuildNumber < 18362 && !CPU_IsSupported_PageGB())
119 return 1;
120 #endif
121
122 return 0;
123 }
124
125 #endif
126
127 }}
128