C++システムログアウト、再起動、シャットダウンを実現する方法

3249 ワード

この機能を実現するには簡単で、主にシステムAPIを呼び出す必要があります.
ExitWindowsEx
機能は、現在のユーザーをログアウトしたり、システムを閉じたり、システムを再起動したりすることです.
WM_が送信されますQUERYENdSESSIONメッセージはすべてのアプリケーションに与えられ、閉じることができるかどうかを決定させます.
関数プロトタイプ
BOOL WINAPI ExitWindowsEx(
  __in  UINT uFlags,
  __in  DWORD dwReason
);

1番目のパラメータは閉じるタイプで、2番目のパラメータは閉じる理由です.
最初のパラメータは次のとおりです.
EWX_LOGOFF 0
EWX_POWEROFF 0x00000008
EWX_REBOOT 0x00000002
EWX_RESTARTAPPS 0x00000040
EWX_SHUTDOWN 0x00000001
このパラメータには、次の2つの値をオプションで含めることもできます.
EWX_FORCE 0 x 0000004このパラメータはシステムを強制的にシャットダウンさせ、アプリケーションにデータを失わせる可能性がある.
EWX_FORECEIFHUNG 0 x 0000010タイムアウト後もアプリケーションプロセスがWM_に応答しない場合QUERYENDSESSIONまたはWM_ENDSESSIONメッセージは、強制的に閉じます.
戻り値:
成功すると0以外の値が返され、失敗すると0が返されます.
GetLastError()でより多くのエラー情報を得ることができます.この関数に加えて、次のことを理解する必要があります.
Windows NT以上のオペレーティングシステムでは、SEをアップグレードする必要があります.SHUTDOWN権限は、シャットダウンを完了することができます.
NT以下のものは必要ありません.例えば95,98,ME
NT以上のシステムは、
Microsoft Windows 2000 (Windows NT 5.0) (1999) (2000-2010) 
Microsoft Windows XP (Windows NT 5.1) (2001-2014) 
Microsoft Windows Server 2003 (Windows NT 5.2) (2003-2015) 
Microsoft Windows Server 2003 R2 (Windows NT 5.2) (2006-2015) 
Microsoft Windows Vista (Windows NT 6.0) (2006-2017) 
Microsoft Windows Server 2008 (Windows NT 6.0) (2008-2018) 
Microsoft Windows 7 (Windows NT 6.1) (2009-2020) 
次に具体的な実装を開始します.
シャットダウン機能の実現
1.システムバージョンを確認し、NT以上であるかどうかを確認し、もしそうであれば権限を上げる
2.システムAPI、ExitWindowsExを呼び出します.
#pragma region     
BOOL ReSetWindows(DWORD dwFlags,BOOL bForce)
{
	//        
	if(dwFlags!=EWX_LOGOFF&&dwFlags!=EWX_REBOOT&&dwFlags!=EWX_SHUTDOWN)
		return FALSE;
	//         ,                 
	OSVERSIONINFO osvi={0};
	//       ,    GetVersionEx           OSVERSIONINFO,      
	//    OSVERSIONINFOEX。    
	osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
	if(!GetVersionEx(&osvi))
	{
		return FALSE;
	}
	//         ,   NT     ,        
	if(osvi.dwPlatformId==VER_PLATFORM_WIN32_NT)
	{
		//EnableShutDownPriv();
	}
	//         ,        。
	dwFlags|=(bForce!=FALSE)?EWX_FORCE:EWX_FORCEIFHUNG;
	//  API
	return ExitWindowsEx(dwFlags,0);
}
権限を上げるコード:
#pragma region         
//             ,          
//  LookupPrivilegeValue      SE_SHUTDOWN_NAME,  
BOOL EnableShutDownPriv()
{
	HANDLE hToken=NULL;
	TOKEN_PRIVILEGES tkp={0};
	//           
	if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
	{
		return FALSE;
	}
	//             LUID,   tkp 
	if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid))
	{
		CloseHandle(hToken);
		return FALSE;
	}
	tkp.PrivilegeCount=1;
	tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
	//  AdjustTokenPrivileges            
	if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
	{
		CloseHandle(hToken);
		return FALSE;
	}
	return TRUE;
}
呼び出し方法:
ReSetWindows(EWX_LOGOFF,false);//  
ReSetWindows(EWX_REBOOT,true);//  
ReSetWindows(EWX_SHUTDOWN,true);//  
みんなはテストする时必ず仮想机の上でテストしなければならなくて、さもなくばシステムを运行して火を消してとても気がふさぐのではありませんか!