Programming/C/C++

C++ UAC Class

acidpop 2012. 2. 28. 18:16
반응형
Elevate.h
// Elevate.h: interface for the CElevate class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ELEVATE_H__E7B50ED2_9C9D_4C00_93E9_C9547465DEFA__INCLUDED_)
#define AFX_ELEVATE_H__E7B50ED2_9C9D_4C00_93E9_C9547465DEFA__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// Windows Vista 이상 OS 에서 관리자 권한 상승을 위한 Class
// 제작 : acidpop.tistory.com
// 날짜 : 2012/02/28

#include <shellapi.h>
#include <shlobj.h>


typedef struct _TOKEN_ELEVATION {
    DWORD TokenIsElevated;
} TOKEN_ELEVATION, *PTOKEN_ELEVATION;

#ifndef CSIDL_PROGRAM_FILES
#define CSIDL_PROGRAM_FILES 0x0026
#endif // CSIDL_PROGRAM_FILES


class CElevate  
{
public:
	CElevate();
	virtual ~CElevate();

public:
	// 특정 프로그램을 관리자 권한으로 실행 하기 위한 함수
	BOOL	ShellExecWithElevation(HWND hWnd, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory);

	// 자기 자신을 관리자 권한으로 다시 시작 하는 함수
	BOOL	SelfExecuteWithElevation();

	// 특정 Url 을 관리자 권한으로 Internet Explorer 를 실행 하는 함수
	BOOL	OpenUrlWithElevation(HWND hWnd, LPCTSTR lpUrl);

	// 권한 상승이 필요한지 여부, 1 - UAC 미지원 OS, 2 - 상태 정보 조회 불가, 3 - 권한 상승 필요, 4 - 권한 상승 되어 있음
	int		GetNeedElevate();

	// OS가 Vista 보다 상위 인지 여부
	BOOL	IsVistaOrHigher(void);
	
	// 권한 체크
	HRESULT IsElevated(BOOL *pElevated);

private:	
	// 관리자 권한으로 실행 하기 위한 가장 기초 함수,ShellExecWithElevation 를 사용하도록 권장
	BOOL	ShellExecWithVerb(HWND hWnd, LPCTSTR lpVerb, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory);
};

#endif // !defined(AFX_ELEVATE_H__E7B50ED2_9C9D_4C00_93E9_C9547465DEFA__INCLUDED_)



Elevate.cpp
// Elevate.cpp: implementation of the CElevate class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Elevate.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CElevate::CElevate()
{

}

CElevate::~CElevate()
{

}



int CElevate::GetNeedElevate()
{
	if (IsVistaOrHigher())
	{
		BOOL bResult = FALSE;
		
		if (SUCCEEDED(IsElevated(&bResult)))
		{
			if (bResult == TRUE)
				return 4; // 이미 Elevation이 완료됨
			else
				return 3; // Elevation이 필요함
		}
		else
			return 2; // 상태 정보를 조회할 수 없음
	}

	return 1; // UAC가 지원되지 않는 운영체제로 판단함
}

BOOL CElevate::IsVistaOrHigher(void)
{
	OSVERSIONINFO versionInfo;
	versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	
	if (GetVersionEx(&versionInfo) &&
		versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
		versionInfo.dwMajorVersion >= 6)
		return TRUE;
	else
		return FALSE;
}



HRESULT CElevate::IsElevated(BOOL *pElevated)
{
	HRESULT hResult = E_FAIL;
	HANDLE hToken = NULL;
	
	if (!IsVistaOrHigher())
		return hResult;
	
	if (!OpenProcessToken(
		GetCurrentProcess(),
		TOKEN_QUERY,
		&hToken))
		return hResult;
	
	TOKEN_ELEVATION te = { 0 };
	DWORD dwReturnLength = 0;
	const int TokenElevation = 20;
	
	if (GetTokenInformation(
		hToken,
		(TOKEN_INFORMATION_CLASS)TokenElevation,
		&te,
		sizeof(te),
		&dwReturnLength))
	{
		hResult = te.TokenIsElevated ? S_OK : S_FALSE;
		
		if (pElevated)
			*pElevated = (te.TokenIsElevated != 0);
	}
	
	CloseHandle(hToken);
	return hResult;
}



BOOL CElevate::ShellExecWithVerb(HWND hWnd, LPCTSTR lpVerb, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
	SHELLEXECUTEINFO executeInfo;
	memset(&executeInfo, 0, sizeof(executeInfo));
	
	executeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
	executeInfo.fMask = 0;
	executeInfo.hwnd = hWnd;
	executeInfo.lpVerb = lpVerb;
	executeInfo.lpFile = lpPath;
	executeInfo.lpParameters = lpParameters;
	executeInfo.lpDirectory = lpDirectory;
	executeInfo.nShow = SW_NORMAL;
	
	return ShellExecuteEx(&executeInfo);
}



BOOL CElevate::ShellExecWithElevation(HWND hWnd, LPCTSTR lpPath, LPCTSTR lpParameters, LPCTSTR lpDirectory)
{
	return ShellExecWithVerb(hWnd, _T("runas"), lpPath, lpParameters, lpDirectory);
}

BOOL CElevate::SelfExecuteWithElevation()
{
	TCHAR pszPathName[_MAX_PATH] = "";

	TCHAR lpParameter[1024] = "";
	
	if(__argc > 1)
	{
		for(int i=1; i<__argc; i++)
		{			
			_tcscat(lpParameter, __argv[i]);
			_tcscat(lpParameter, " ");
		}
	}

	::GetModuleFileName(::AfxGetInstanceHandle(), pszPathName, _MAX_PATH);

	//PathRemoveFileSpec(pszPathName);
	return ShellExecWithElevation(NULL, pszPathName, lpParameter, _T(""));
}

BOOL CElevate::OpenUrlWithElevation(HWND hWnd, LPCTSTR lpUrl)
{
	_TCHAR lpBuffer[MAX_PATH + 1];
	
	if (!SHGetSpecialFolderPath(hWnd, lpBuffer, CSIDL_PROGRAM_FILES, 0))
		return FALSE;
	
	_tcscat(lpBuffer, _T("\\Internet Explorer\\iexplore.exe"));
	return ShellExecWithElevation(hWnd, lpBuffer, lpUrl, _T(""));
}


<SPAN id=tx_marker_caret></SPAN>



위 클래스를 이용하여 ShellExecWithElevation  함수를 이용하면 응용 프로그램도 관리자 권한으로 실행하도록

요청할 수 있다.