// Windows/SecurityUtils.cpp | |
#include "StdAfx.h" | |
#include "SecurityUtils.h" | |
namespace NWindows { | |
namespace NSecurity { | |
/* | |
bool MyLookupAccountSid(LPCTSTR systemName, PSID sid, | |
CSysString &accountName, CSysString &domainName, PSID_NAME_USE sidNameUse) | |
{ | |
DWORD accountNameSize = 0, domainNameSize = 0; | |
if (!::LookupAccountSid(systemName, sid, | |
accountName.GetBuffer(0), &accountNameSize, | |
domainName.GetBuffer(0), &domainNameSize, sidNameUse)) | |
{ | |
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) | |
return false; | |
} | |
bool result = BOOLToBool(::LookupAccountSid(systemName, sid, | |
accountName.GetBuffer(accountNameSize), &accountNameSize, | |
domainName.GetBuffer(domainNameSize), &domainNameSize, sidNameUse)); | |
accountName.ReleaseBuffer(); | |
domainName.ReleaseBuffer(); | |
return result; | |
} | |
*/ | |
static void SetLsaString(LPWSTR src, PLSA_UNICODE_STRING dest) | |
{ | |
int len = (int)wcslen(src); | |
dest->Length = (USHORT)(len * sizeof(WCHAR)); | |
dest->MaximumLength = (USHORT)((len + 1) * sizeof(WCHAR)); | |
dest->Buffer = src; | |
} | |
/* | |
static void MyLookupSids(CPolicy &policy, PSID ps) | |
{ | |
LSA_REFERENCED_DOMAIN_LIST *referencedDomains = NULL; | |
LSA_TRANSLATED_NAME *names = NULL; | |
NTSTATUS nts = policy.LookupSids(1, &ps, &referencedDomains, &names); | |
int res = LsaNtStatusToWinError(nts); | |
LsaFreeMemory(referencedDomains); | |
LsaFreeMemory(names); | |
} | |
*/ | |
#ifndef _UNICODE | |
typedef BOOL (WINAPI * LookupAccountNameWP)( | |
LPCWSTR lpSystemName, | |
LPCWSTR lpAccountName, | |
PSID Sid, | |
LPDWORD cbSid, | |
LPWSTR ReferencedDomainName, | |
LPDWORD cchReferencedDomainName, | |
PSID_NAME_USE peUse | |
); | |
#endif | |
static PSID GetSid(LPWSTR accountName) | |
{ | |
#ifndef _UNICODE | |
HMODULE hModule = GetModuleHandle(TEXT("Advapi32.dll")); | |
if (hModule == NULL) | |
return NULL; | |
LookupAccountNameWP lookupAccountNameW = (LookupAccountNameWP)GetProcAddress(hModule, "LookupAccountNameW"); | |
if (lookupAccountNameW == NULL) | |
return NULL; | |
#endif | |
DWORD sidLen = 0, domainLen = 0; | |
SID_NAME_USE sidNameUse; | |
if (! | |
#ifdef _UNICODE | |
::LookupAccountNameW | |
#else | |
lookupAccountNameW | |
#endif | |
(NULL, accountName, NULL, &sidLen, NULL, &domainLen, &sidNameUse)) | |
{ | |
if (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) | |
{ | |
PSID pSid = ::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sidLen); | |
LPWSTR domainName = (LPWSTR)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (domainLen + 1) * sizeof(WCHAR)); | |
BOOL res = | |
#ifdef _UNICODE | |
::LookupAccountNameW | |
#else | |
lookupAccountNameW | |
#endif | |
(NULL, accountName, pSid, &sidLen, domainName, &domainLen, &sidNameUse); | |
::HeapFree(GetProcessHeap(), 0, domainName); | |
if (res) | |
return pSid; | |
} | |
} | |
return NULL; | |
} | |
#define MY__SE_LOCK_MEMORY_NAME L"SeLockMemoryPrivilege" | |
bool AddLockMemoryPrivilege() | |
{ | |
CPolicy policy; | |
LSA_OBJECT_ATTRIBUTES attr; | |
attr.Length = sizeof(attr); | |
attr.RootDirectory = NULL; | |
attr.ObjectName = NULL; | |
attr.Attributes = 0; | |
attr.SecurityDescriptor = NULL; | |
attr.SecurityQualityOfService = NULL; | |
if (policy.Open(NULL, &attr, | |
// GENERIC_WRITE) | |
POLICY_ALL_ACCESS) | |
// STANDARD_RIGHTS_REQUIRED, | |
// GENERIC_READ | GENERIC_EXECUTE | POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES) | |
!= 0) | |
return false; | |
LSA_UNICODE_STRING userRights; | |
wchar_t s[128] = MY__SE_LOCK_MEMORY_NAME; | |
SetLsaString(s, &userRights); | |
WCHAR userName[256 + 2]; | |
DWORD size = 256; | |
if (!GetUserNameW(userName, &size)) | |
return false; | |
PSID psid = GetSid(userName); | |
if (psid == NULL) | |
return false; | |
bool res = false; | |
/* | |
PLSA_UNICODE_STRING userRightsArray; | |
ULONG countOfRights; | |
NTSTATUS status = policy.EnumerateAccountRights(psid, &userRightsArray, &countOfRights); | |
if (status != 0) | |
return false; | |
bool finded = false; | |
for (ULONG i = 0; i < countOfRights; i++) | |
{ | |
LSA_UNICODE_STRING &ur = userRightsArray[i]; | |
if (ur.Length != s.Length() * sizeof(WCHAR)) | |
continue; | |
if (wcsncmp(ur.Buffer, s, s.Length()) != 0) | |
continue; | |
finded = true; | |
res = true; | |
break; | |
} | |
if (!finded) | |
*/ | |
{ | |
/* | |
LSA_ENUMERATION_INFORMATION *enums; | |
ULONG countReturned; | |
NTSTATUS status = policy.EnumerateAccountsWithUserRight(&userRights, &enums, &countReturned); | |
if (status == 0) | |
{ | |
for (ULONG i = 0; i < countReturned; i++) | |
MyLookupSids(policy, enums[i].Sid); | |
if (enums) | |
::LsaFreeMemory(enums); | |
res = true; | |
} | |
*/ | |
NTSTATUS status = policy.AddAccountRights(psid, &userRights); | |
if (status == 0) | |
res = true; | |
// ULONG res = LsaNtStatusToWinError(status); | |
} | |
HeapFree(GetProcessHeap(), 0, psid); | |
return res; | |
} | |
}} | |