1// Windows/SecurityUtils.cpp 2 3#include "StdAfx.h" 4 5#include "SecurityUtils.h" 6 7namespace NWindows { 8namespace NSecurity { 9 10/* 11bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, 12 CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) 13{ 14 DWORD accountNameSize = 0, domainNameSize = 0; 15 16 if (!::LookupAccountSid(systemName, sid, 17 accountName.GetBuf(0), &accountNameSize, 18 domainName.GetBuf(0), &domainNameSize, sidNameUse)) 19 { 20 if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) 21 return false; 22 } 23 DWORD accountNameSize2 = accountNameSize, domainNameSize2 = domainNameSize; 24 bool result = BOOLToBool(::LookupAccountSid(systemName, sid, 25 accountName.GetBuf(accountNameSize), &accountNameSize2, 26 domainName.GetBuf(domainNameSize), &domainNameSize2, sidNameUse)); 27 accountName.ReleaseBuf_CalcLen(accountNameSize); 28 domainName.ReleaseBuf_CalcLen(domainNameSize); 29 return result; 30} 31*/ 32 33static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) 34{ 35 const size_t len = (size_t)wcslen(src); 36 dest->Length = (USHORT)(len * sizeof(WCHAR)); 37 dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); 38 dest->Buffer = src; 39} 40 41/* 42static void MyLookupSids(CPolicy &policy, PSID ps) 43{ 44 LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; 45 LSA_TRANSLATED_NAME *names = NULL; 46 NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); 47 int res = LsaNtStatusToWinError(nts); 48 LsaFreeMemory(referencedDomains); 49 LsaFreeMemory(names); 50} 51*/ 52 53extern "C" { 54 55#ifndef _UNICODE 56typedef BOOL (WINAPI * Func_LookupAccountNameW)( 57 LPCWSTR lpSystemName, 58 LPCWSTR lpAccountName, 59 PSID Sid, 60 LPDWORD cbSid, 61 LPWSTR ReferencedDomainName, 62 LPDWORD cchReferencedDomainName, 63 PSID_NAME_USE peUse 64 ); 65#endif 66 67} 68 69static PSID GetSid(LPWSTR accountName) 70{ 71 #ifndef _UNICODE 72 const HMODULE hModule = GetModuleHandle(TEXT("advapi32.dll")); 73 if (!hModule) 74 return NULL; 75 const 76 Func_LookupAccountNameW lookupAccountNameW = Z7_GET_PROC_ADDRESS( 77 Func_LookupAccountNameW, hModule, 78 "LookupAccountNameW"); 79 if (!lookupAccountNameW) 80 return NULL; 81 #endif 82 83 DWORD sidLen = 0, domainLen = 0; 84 SID_NAME_USE sidNameUse; 85 if (! 86 #ifdef _UNICODE 87 ::LookupAccountNameW 88 #else 89 lookupAccountNameW 90 #endif 91 (NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) 92 { 93 if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) 94 { 95 const PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); 96 LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); 97 const BOOL res = 98 #ifdef _UNICODE 99 ::LookupAccountNameW 100 #else 101 lookupAccountNameW 102 #endif 103 (NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); 104 ::HeapFree(GetProcessHeap(), 0, domainName); 105 if (res) 106 return pSid; 107 } 108 } 109 return NULL; 110} 111 112#define Z7_WIN_SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" 113 114bool AddLockMemoryPrivilege() 115{ 116 CPolicy policy; 117 LSA_OBJECT_ATTRIBUTES attr; 118 attr.Length = sizeof(attr); 119 attr.RootDirectory = NULL; 120 attr.ObjectName = NULL; 121 attr.Attributes = 0; 122 attr.SecurityDescriptor = NULL; 123 attr.SecurityQualityOfService = NULL; 124 if (policy.Open(NULL, &attr, 125 // GENERIC_WRITE) 126 POLICY_ALL_ACCESS) 127 // STANDARD_RIGHTS_REQUIRED, 128 // GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) 129 != 0) 130 return false; 131 LSA_UNICODE_STRING userRights; 132 wchar_t s[128] = Z7_WIN_SE_LOCK_MEMORY_NAME; 133 SetLsaString(s, &userRights); 134 WCHAR userName[256 + 2]; 135 DWORD size = 256; 136 if (!GetUserNameW(userName, &size)) 137 return false; 138 const PSID psid = GetSid(userName); 139 if (psid == NULL) 140 return false; 141 bool res = false; 142 143 /* 144 PLSA_UNICODE_STRING userRightsArray; 145 ULONG countOfRights; 146 NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); 147 if (status != 0) 148 return false; 149 bool finded = false; 150 for (ULONG i = 0; i < countOfRights; i++) 151 { 152 LSA_UNICODE_STRING &ur = userRightsArray[i]; 153 if (ur.Length != s.Length() * sizeof(WCHAR)) 154 continue; 155 if (wcsncmp(ur.Buffer, s, s.Length()) != 0) 156 continue; 157 finded = true; 158 res = true; 159 break; 160 } 161 if (!finded) 162 */ 163 { 164 /* 165 LSA_ENUMERATION_INFORMATION *enums; 166 ULONG countReturned; 167 NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); 168 if (status == 0) 169 { 170 for (ULONG i = 0; i < countReturned; i++) 171 MyLookupSids(policy, enums[i].Sid); 172 if (enums) 173 ::LsaFreeMemory(enums); 174 res = true; 175 } 176 */ 177 const NTSTATUS status = policy.AddAccountRights(psid, &userRights); 178 if (status == 0) 179 res = true; 180 // ULONG res = LsaNtStatusToWinError(status); 181 } 182 HeapFree(GetProcessHeap(), 0, psid); 183 return res; 184} 185 186}} 187