반응형
ExitWindowsEx 함수를 사용하여 컴퓨터를 종료, 재시작, 로그아웃 시키는 방법은 매우 간단합니다.
이 함수의 첫번째 인자에 아래 나열된 값중에서 원하는 값을 조합해서 명시만 해주면 되기 때문입니다.
1. EWX_LOGOFF : 사용중인 프로그램을 종료하고 시스템을 LOG OFF 시킨다.
2. EWX_POWEROFF : 시스템을 종료하고 전원을 끊다.
3. EWX_REBOOT : 시스템을 종료시킨 후 시스템을 재시작 한다.
4. EWX_SHUTDOWN : 사용자가 시스템의 전원을 끌 수 있도록 시스템을 종료한다.
5. EWX_FORCE : 강제로 프로세스를 종료시킨다.
2. EWX_POWEROFF : 시스템을 종료하고 전원을 끊다.
3. EWX_REBOOT : 시스템을 종료시킨 후 시스템을 재시작 한다.
4. EWX_SHUTDOWN : 사용자가 시스템의 전원을 끌 수 있도록 시스템을 종료한다.
5. EWX_FORCE : 강제로 프로세스를 종료시킨다.
이 함수를 사용할때 주의해야할 점은 윈도우즈 NT 계열(Windows NT, Windows 2000, Windows XP..)의
운영체제에서는 종료를 위해서 ExitWindowEx 함수를 사용하는 프로세스가 SE_SHUTDOWN_NAME
이라는 권한을 가지고 있어야 하기 때문에 해당 권한을 얻는 기능을 추가해주여야 한다는 것입니다.
( 윈도우즈 98, Me와 같은 운영체제에서는 권한이 필요 없습니다. )
따라서 ExitWindowsEx 함수를 호출하기 전에 먼저 운영체제의 버전을 체크하는 코드가 있어야 합니다.
// 현재 응용프로그램이 실행되고 있는 윈도우즈의 버전을 반환하도록 작성된 함수입니다.
// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
// [ 반환값 : 의미 ]
// -1 : 버전얻기 실패, 1 : Windows 95, 2 : Windows 98, 3 : Windows ME, 4 : Windows NT,
// 5 : Windows 2000, 6 : Windows XP
// -1 : 버전얻기 실패, 1 : Windows 95, 2 : Windows 98, 3 : Windows ME, 4 : Windows NT,
// 5 : Windows 2000, 6 : Windows XP
char GetOSVersionType()
{
// 계산된 윈도우즈 버전을 저장할 변수
char version = -1;
char version = -1;
// 윈도우즈 버전에 관련된 정보를 얻어올 변수
OSVERSIONINFOEX osvi;
OSVERSIONINFOEX osvi;
// OSVERSIONINFOEX 구조체 값을 얻었는지 OSVERSIONINFO 구조체값을 얻었는지를
// 구분할 변수 ( 0 이면, OSVERSIONINFO 구조체 정보를 얻었다는 뜻입니다. )
BOOL version_ex_flag = 0;
BOOL version_ex_flag = 0;
// 운영체제의 버전과 관련된 정보를 얻기 위해 구조체 변수를 초기화합니다.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
// 현재 운영체제의 버전을 알수 없기 때문에 OSVERSIONINFOEX 속성으로 버전정보를 얻습니다.
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
// GetVersionEx 함수를 사용하여 현재의 운영체제 정보를 얻습니다.
// OSVERSIONINFOEX 값을 설정하고 호출했기 대문에 윈도우 NT 4.0 SP6 이상 및 그 이후 버전의
// OSVERSIONINFOEX 값을 설정하고 호출했기 대문에 윈도우 NT 4.0 SP6 이상 및 그 이후 버전의
// 윈도우가 아니라면 이 함수는 실패할 것입니다.
if(!(version_ex_flag = GetVersionEx((OSVERSIONINFO *)&osvi))){
if(!(version_ex_flag = GetVersionEx((OSVERSIONINFO *)&osvi))){
// 윈도우즈 버전이 낮아서 OSVERSIONINFOEX 형식으로 값을 얻을수 없는 경우...
// OSVERSIONINFO 형식으로 재설정하고 값을 얻습니다.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if(!GetVersionEx((OSVERSIONINFO *)&osvi)) return -1;
}
if(!GetVersionEx((OSVERSIONINFO *)&osvi)) return -1;
}
// 얻어온 OSVERSIONINFOEX 구조체 변수의 값을 이용하여 버전을 구별합니다.
switch(osvi.dwPlatformId){
// NT 기술 기반의 운영체제인 경우
case VER_PLATFORM_WIN32_NT:
if(osvi.dwMajorVersion <= 4) version = 4;
switch(osvi.dwPlatformId){
// NT 기술 기반의 운영체제인 경우
case VER_PLATFORM_WIN32_NT:
if(osvi.dwMajorVersion <= 4) version = 4;
else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) version = 5;
else if(version_ex_flag){
if(osvi.dwMajorVersion == 5) version = 6; // XP
else if(osvi.dwMajorVersion == 6) version = 7; // 비스타...
}
break;
// 윈도우즈 9x 기반의 운영체제인 경우
case VER_PLATFORM_WIN32_WINDOWS:
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) version = 1;
else if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10) version = 2;
else if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) version = 3;
break;
}
return version;
}
}
// 현재 운영체제가 NT 계열인 경우, SE_SHUTDOWN_NAME 레벨의 권한 등급을
// 가지고 있어야 하기 때문에 아래의 함수를 이용하여 권한을 얻습니다.
char GetNtPrivilege()
{
HANDLE h_token;
TOKEN_PRIVILEGES privilege_info;
{
HANDLE h_token;
TOKEN_PRIVILEGES privilege_info;
// 현재 프로세스의 권한과 관련된 정보를 변경하기 위해 토큰정보를 엽니다.
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES |
TOKEN_QUERY, &h_token)){
// 권한과 관련된 정보 접근에 실패함..
return 0;
}
TOKEN_QUERY, &h_token)){
// 권한과 관련된 정보 접근에 실패함..
return 0;
}
// 현재 프로세스가 SE_SHUTDOWN_NAME 권한을 사용할수 있도록 설정한다.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &privilege_info.Privileges[0].Luid);
privilege_info.PrivilegeCount = 1;
privilege_info.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
privilege_info.PrivilegeCount = 1;
privilege_info.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// 지정한 값으로 권한을 조정한다.
AdjustTokenPrivileges(h_token, FALSE, &privilege_info, 0, (PTOKEN_PRIVILEGES)NULL, 0);
AdjustTokenPrivileges(h_token, FALSE, &privilege_info, 0, (PTOKEN_PRIVILEGES)NULL, 0);
if(GetLastError() != ERROR_SUCCESS){
// 권한 조정에 실패한 경우...
// 권한 조정에 실패한 경우...
return 0;
}
}
return 1;
}
}
// 컴퓨터를 끌때 사용할 함수
void PowerOff()
{
{
if(GetOSVersionType()) <= 3{
// 현재 운영체제가 Windows 95, Windows 98, Windows ME 인 경우...
ExitWindowsEx(EWX_LOGOFF | EWX_POWEROFF | EWX_SHUTDOWN, 0);
ExitWindowsEx(EWX_FORCE, 0);
} else if(GetNtPrivilege()){
ExitWindowsEx(EWX_LOGOFF | EWX_POWEROFF | EWX_SHUTDOWN, 0);
ExitWindowsEx(EWX_FORCE, 0);
} else if(GetNtPrivilege()){
// 현재 운영체제가 Windows NT, Windows 2000, Windows XP 인 경우...
ExitWindowsEx(EWX_FORCE | EWX_POWEROFF, 0);
}
}
//////////////////
int CTimerDlg::Window_ShutDown(void)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if( !OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken ) ) return 0;
if( !LookupPrivilegeValue( NULL,
SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid ) ) return 0;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if( !AdjustTokenPrivileges( hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES)NULL,
0 ) ) return 0;
//////////////////
int CTimerDlg::Window_ShutDown(void)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if( !OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken ) ) return 0;
if( !LookupPrivilegeValue( NULL,
SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid ) ) return 0;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if( !AdjustTokenPrivileges( hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES)NULL,
0 ) ) return 0;
ExitWindowsEx( EWX_SHUTDOWN | EWX_FORCE, 0 );
return 0;
}
return 0;
}
반응형
'프로그래머의 길 > C & C++' 카테고리의 다른 글
CSliderCtrl Focus 테두리(점선) 없애는 방법 (0) | 2010.10.27 |
---|---|
리스트 컨트롤 / 콤보 박스 글씨 색 바꾸기 (0) | 2010.07.07 |
CStringT::Tokenize. (0) | 2009.12.02 |
complex 예제 (복소수 연산) & conj (켤레 복소수) (0) | 2009.12.01 |
Class Map 사용예제 (0) | 2009.11.30 |