#include "StdAfx.h"
#include "SecDesc.h"
#include <aclapi.h >

CSecDesc::CSecDesc(void)
{
	m_eaCount = 0;
	m_pDacl = NULL;
}

CSecDesc::~CSecDesc(void)
{
	m_eaCount = 0;
	if(m_pDacl)
	{
		::LocalFree(m_pDacl);
		m_pDacl = NULL;
	}

	for(int i=0;i<m_trustyNames.GetCount();i++)
		delete m_trustyNames[i];
	m_trustyNames.RemoveAll();
}


///////////////////////////////////////////////////////////////////////////////////////////////
//	SD生成
///////////////////////////////////////////////////////////////////////////////////////////////
/*!
	SD生成
*/
int CSecDesc::BuildSA()
{
	//	SD初期化
	InitializeSecurityDescriptor(&m_sd, SECURITY_DESCRIPTOR_REVISION);

	//	DACL生成
	if(SetEntriesInAcl(m_eaCount, m_ea, NULL, &m_pDacl) != ERROR_SUCCESS )
	{
		TRACE("%d\n", GetLastError());
		return(-1);
	}

	//	SDへ設定
	SetSecurityDescriptorDacl(&m_sd, TRUE, m_pDacl, FALSE);

	//	AS設定
	m_sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
	m_sa.bInheritHandle       = FALSE;
	m_sa.lpSecurityDescriptor = &m_sd;

	return(0);
}

/*!
	Localを許可するSA生成
*/
int CSecDesc::BuildLocalSA(DWORD AccessPermissions)
{
	if(AddUserByName("Local", AccessPermissions, GRANT_ACCESS, NO_INHERITANCE))
		return(-1);

	//	自分も追加
	AddUserByName(GetCurrentProcessUser(), AccessPermissions, GRANT_ACCESS, NO_INHERITANCE);

	if(BuildSA())
		return(-1);

	return(0);
}

///////////////////////////////////////////////////////////////////////////////////////////////
//	ユーザの追加
///////////////////////////////////////////////////////////////////////////////////////////////
/*!
	ユーザ追加
*/
int CSecDesc::AddUserByName(CString name, DWORD AccessPermissions, ACCESS_MODE AccessMode, DWORD Inheritance)
{
	if(m_eaCount >= MAX_EA)
		return(-1);

	if(name.IsEmpty())
		return(-1);

	//	トラスティコピー
	m_trustyNames.Add(new char[name.GetLength() + 1]);
	strcpy_s(m_trustyNames[m_eaCount], name.GetLength() + 1, name);

	BuildExplicitAccessWithName(&m_ea[m_eaCount], m_trustyNames[m_eaCount], AccessPermissions, AccessMode, Inheritance);
	m_eaCount++;
	return(0);
}


/*！
	現在のユーザを取得
*/
CString CSecDesc::GetCurrentProcessUser()
{
	HANDLE	hToken;
	if(!OpenProcessToken(::GetCurrentProcess(), TOKEN_READ, &hToken))
	{
		//	エラー
		return("");
	}
	else
	{
		UCHAR InfoBuffer[1000],szAccountName[MAX_PATH], szDomainName[MAX_PATH];
		PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
		DWORD dwInfoBufferSize,dwAccountSize = MAX_PATH, dwDomainSize = MAX_PATH;
		SID_NAME_USE snu;

		if(!GetTokenInformation(hToken,TokenUser,InfoBuffer, 1000, &dwInfoBufferSize))
		{
			SAFE_CLOSE_HANDLE(hToken);
			return("");
		}

		if(!LookupAccountSid(NULL, pTokenUser->User.Sid, (LPSTR)szAccountName, &dwAccountSize,(LPSTR)szDomainName, &dwDomainSize, &snu))
		{
			SAFE_CLOSE_HANDLE(hToken);
			return("");
		}

		SAFE_CLOSE_HANDLE(hToken);

		return(CString(szAccountName));
	}
}
