xref: /aosp_15_r20/external/lzma/CPP/Windows/MemoryLock.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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