张雪迎高清手机壁纸:ExitWindowsEX函数的使用

来源:百度文库 编辑:偶看新闻 时间:2024/05/09 16:04:12
ExitWindowsEX()函数用来退出、重启或注销系统。   函数原型:   BOOL ExitWindowsEx(   UINT uFlags, // 关闭参数   DWORD dwReserved // 系统保留,一般取0   );   参数:uFlags   指定关闭的类型。此参数必须有下列值的组合: EWX_FORCE   强制终止进程。当此标志设置,Windows不会发送消息WM_QUERYENDSESSION和WM_ENDSESSION的消息给目前在系统中运行的程序。这可能会导致应用程序丢失数据。因此,你应该只在紧急情况下使用此标志。   EWX_LOGOFF   关闭所有进程,然后注销用户。   EWX_POWEROFF   关闭系统并关闭电源。该系统必须支持断电。   Windows要求:   Windows NT中调用进程必须有 SE_SHUTDOWN_NAME 特权。   Windows 9X中:可以直接调用。   EWX_REBOOT   关闭系统,然后重新启动系统。   Windows要求:   Windows NT中:调用进程必须有SE_SHUTDOWN_NAME特权。   Windows 9X中:可以直接调用。   EWX_SHUTDOWN   关闭系统,安全地关闭电源。所有文件缓冲区已经刷新到磁盘上,所有正在运行的进程已经停止。   Windows要求:   Windows NT中:调用进程必须有SE_SHUTDOWN_NAME特权。   Windows 9X中:可以直接调用。   参数:dwReserved   保留,这参数被忽略。一般取0。   返回值   如果函数成功,返回值为非零。   如果函数失败,返回值是零。想获得更多错误信息,请调用GetLastError函数。    ExitWindowsEx函数返回后,启动了关闭。关闭或注销。   在关机或登录操作中,应用程序在允许关闭的时间具体数额内回应关机请求。如果时间到期时,Windows会显示一个对话框,允许用户强行关闭应用程序:关闭、重试,或取消关机要求。如果存在EWX_FORCE指定值,Windows会关闭应用程序而不显示该对话框。   Windows NT中:关闭或重新启动系统,调用进程必须使用AdjustTokenPrivileges函数使SE_SHUTDOWN_NAME特权。Windows 95中:安全特权,不支持或需要。    Windows 9X:   ExitWindowsEx(EWX_SHUTDOWN, 0); //关闭系统   ExitWindowsEx(EWX_REBOOT, 0); //重启系统   Windows NT/2000/XP:   以下给出一个函数   如果不是MFC,加入以下语句在该函数之前   #define BOOL int   #define TRUE 1   #define FALSE 0   如果是,直接加入   BOOL SystemShutdown()   {   HANDLE hToken;   TOKEN_PRIVILEGES tkp;   /* OpenProcessToken() 这个函数的作用是打开一个进程的访问令牌   GetCurrentProcess() 函数的作用是得到本进程的句柄*/   if (!OpenProcessToken(GetCurrentProcess(),   TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken))   return FALSE;   // LookupPrivilegeValue() 的作用是修改进程的权限   LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,   &tkp.Privileges[0].Luid);   tkp.PrivilegeCount = 1; // one privilege to set 赋给本进程特权   tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   // AdjustTokenPrivileges()的作用是通知Windows NT修改本进程的权利   AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,   (PTOKEN_PRIVILEGES)NULL, 0);   if (GetLastError() != ERROR_SUCCESS) //失败   return FALSE;   if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, 0)) //参数在这里设置。强行退出WINDOWS(EWX_FORCE)。   return FALSE;   return TRUE;   }  2、

“系统ShutDown”属于Windows系统的一种基本服务。功能上有“关闭系统”,“注销用户”,“锁定工作站”3中操作。SDK中提供了几个函数,来对此服务进行调用。

“关闭系统”功能使计算机可以被安全的关闭。所有在文件系统里缓冲的内容都被强制写入磁盘。然后,显示相应的对话框,提示用户计算机将被关闭或者已经准备好被关闭。可选的情况一般是计算机在关闭后重起,而不是直接切断电源。

如果一个进程调用“注销”功能函数,则该进程所在的安全环境范围内的所有进程都被终止,使当前的用户退出系统。一个登陆对话框被显示,期待新用户的登陆。

“锁定工作站”功能使你可以在离开计算机的时候,保护计算机屏幕不被未授权的用户看到。要解除锁定,必须用管理员或着授权用户的帐号和密码重新登陆。

如何关闭系统:

程序可以用两种方式关闭本地或远程计算机
直接关闭系统
关闭系统并重启
Windows NT/2000 及后续版本: 程序必须拥有SE_SHUTDOWN_NAME权限才能成功调用关闭函数。


ExitWindowsEx函数可以用来关闭系统。如函数成功调用,系统对每个窗口发送WM_QUERYENDSESSION 消息,询问窗口所属的程序是否可以被终止。收到此消息的程序应该进行响应,清除环境释放资源,然后返回TRUE表示自己可以被终止。然而调用ExitWindowEx的时候如果指定了EXW_FORCE,则系统强行终止相关的进程并关闭,这样可能导致数据的丢失。

这是一段在NT/2000中调用ExitWindowEx关闭系统的程序(强制关闭所有程序)。

在windows95/98/me中直接调用ExitWindowEx即可。
-----------------------------------------------------------------------------------------------------------


HANDLE hToken;
TOKEN_PRIVILEGES tkp;

// Get a token for this process.

if (!OpenProcessToken(GetCurrentProcess(),

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))


Error("OpenProcessToken");

// Get the LUID for the shutdown privilege.

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);

tkp.PrivilegeCount = 1; // one privilege to set

tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

// Get the shutdown privilege for this process.

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

(PTOKEN_PRIVILEGES)NULL, 0);

// Cannot test the return value of AdjustTokenPrivileges.

if (GetLastError() != ERROR_SUCCESS)

error("AdjustTokenPrivileges");

// Shut down the system and force all applications to close.

if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0))

error("ExitWindowsEx");

-----------------------------------------------------------------------------------------------------------

Windows NT/2000以及后续版本:

InitiateSystemShutdown函数可以指定一段延时,在进行延时计数的时候,在将被关闭的目标计算机上显示一个对话框,提示用户尽快注销。一旦计数结束,系统则立刻被关闭。在此之前,可以调用AbortSystemShutdown函数停止计数,取消相应的关闭操作。InitiateSystemShutdown也可以指定让系统重启。


InitiateSystemShutdown有一个参数LPTSTR lpMachineName,可以指定为网络上的计算机名字,也就是说,可以关闭网络上的他计算机(如果你的用户在该计算机上有足够的权限的话)。


以下这个例子调用InitiateSystemShutdown函数关闭用户已经登陆的本地计算机(要关闭远程计算机将InitSystemShutdown第一个参数由NULL改为正确的计算机名字或)。同样的,也需要先获得SE_SHUTDOWN_NAME权限。


---------------------------------------------------------------------------------------------------------

HANDLE hToken; // handle to process token

TOKEN_PRIVILEGES tkp; // pointer to token structure

BOOL fResult; // system shutdown flag

// Get the current process token handle so we can get shutdown

// privilege.

if (!OpenProcessToken(GetCurrentProcess(),

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))

ErrorHandler("OpenProcessToken failed.");

// Get the LUID for shutdown privilege.

LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);

tkp.PrivilegeCount = 1; // one privilege to set

tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

// Get shutdown privilege for this process.

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

(PTOKEN_PRIVILEGES) NULL, 0);

// Cannot test the return value of AdjustTokenPrivileges.

if (GetLastError() != ERROR_SUCCESS)

ErrorHandler("AdjustTokenPrivileges enable failed.");

// Display the shutdown dialog box and start the time-out countdown.

fResult = InitiateSystemShutdown( NULL, // shut down local computer

"Click on the main window and press \

the Escape key to cancel shutdown.", // message to user

20, // time-out period

FALSE, // ask user to close apps

TRUE); // reboot after shutdown


if (!fResult)


{

ErrorHandler("InitiateSystemShutdown failed.");

}
// Disable shutdown privilege.


tkp.Privileges[0].Attributes = 0;


AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,


(PTOKEN_PRIVILEGES) NULL, 0);


if (GetLastError() != ERROR_SUCCESS)


{

ErrorHandler("AdjustTokenPrivileges disable failed.");

}

---------------------------------------------------------------------------------------------
而使用AbortSystemShutoown取消InitialSystemShutdown操作的代码如下(记住要在延时结束前执行才能起作用


// Get the current process token handle so we can get shutdown

// privilege.


if (!OpenProcessToken(GetCurrentProcess(),

TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))

{

ErrorHandler("OpenProcessToken failed.");

}


// Get the LUID for shutdown privilege.


LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,

&tkp.Privileges[0].Luid);


tkp.PrivilegeCount = 1; // one privilege to set


tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;


// Get shutdown privilege for this process.


AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

(PTOKEN_PRIVILEGES)NULL, 0);


// Cannot test the return value of AdjustTokenPrivileges.


if (GetLastError() != ERROR_SUCCESS)


{

ErrorHandler("AdjustTokenPrivileges enable failed.");

}

// Prevent the system from shutting down.

fResult = AbortSystemShutdown(NULL);

if (!fResult)

{

ErrorHandler("AbortSystemShutdown failed.");

}

// Disable shutdown privilege.

tkp.Privileges[0].Attributes = 0;

AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,

(PTOKEN_PRIVILEGES) NULL, 0);

if (GetLastError() != ERROR_SUCCESS)

{

ErrorHandler("AdjustTokenPrivileges disable failed.");

}

break;

关于用户权限(Privileges)的详细信息,可以参见MSDN

如何注销当前用户


可以使用ExitWindows或ExitWindowsEx函数注销当前用户。

在默认的情况下,当程序调用ExitWindows或ExitWindowsEx注销的时候,WM_QUERYENDSESSION消息也被发送到系统内的每个窗口。窗口所属的程序响应此消息并且返回TRUE表示可以被关闭,如果任意一个程序返回FALSE,注销操作将被取消。

Windows NT/2000以及后续版本:

当一个程序响应WM_QUERYENDSESSION并返回TRUE,那么它就会立刻接受到WM_ENDSESSION消息并马上结束,而不管其他的程序是怎么样回应WM_QUERYENDSESSION消息的。

Windows 95/98/Me:只有当系统内所有的程序都对WM_QUERYENDSESSION消息回应TRUE之后,他们才会一起接受到WM_ENDSESSION 消息,然后结束。

如果要强制关闭所有的程序,使用ExitWindowsEx函数,指定EXW_FORCE标志。如果这样做,系统不发送WM_QUERYENDSESSION 消息,而直接终止正在运行的程序。

在注销的时候,系统还向每一个进程发送CTRL_LOGOFF_EVENT 控制码。控制台程序可以注册一个HandlerRoutine例程来处理这个控制码(使用SetConsoleCtrlHandler函数)。(更多的关于控制台的控制码,参见MSDN里“HandlerRoutine”有关章节)

综上所述:只有所有的程序都允许退出,注销操作才能成功。如果某一个程序响应WM_QUERYENDSESSION并返回FALSE ,用户则不能被注销。这样就可以写出防止用户注销或关闭的程序(非强制情况)。

//这是注销当前用户的代码

ExitWindows(0, 0);

//响应WM_QUERYENDSESSION消息,如果在弹出消息框里选择NO,则取消注销。

case WM_QUERYENDSESSION:

{

int r;

r = MessageBox(NULL, "Shut down?","WM_QUERYENDSESSION", MB_YESNO);

// Return TRUE to allow shutdown, FALSE to stop.

return r == IDYES;

break;

}

如何锁定工作站

使用LockWorkStation函数即可锁定工作站。系统会显示一个锁定对话框,告诉用户此工作站正在使用并且已经被锁定,可以被执行锁定的用户或管理员解锁,解锁的方式是按下CTRL_ALT_DEL并用正确的帐号和密码登陆。

LockWorkStation函数成功调用的条件是:

调用者必须是运行在系统交互桌面上的一般进程。

必须已经有用户登陆到系统

工作站未被锁定。

拥有正常窗口和消息队列的程序通过WM_QUERYENDSESSION或WM_ENDSESSION消息获得关闭通知。

控制台则是在其控制流程(Handle Routines)里接受关闭通知。要注册一个控制台控制流程,应该使用SetConsoleCtrlHandler函数

服务程序在其控制流程里接受退出通知。要注册一个服务控制流程,应该使用RegisterServiceCtrlHandlerEx函数。

关闭系统函数列表

函数名                函数功能描述

AbortSystemShutdown          取消由InitSystemShutdown引起的系统关闭操作

ExitWindows              注销当前用户

ExitWindowsEx             注销用户,关闭计算机,关闭计算机并且重启

InitiateSystemShutdown         发起关闭系统操作,可以选择关闭后重启

InitiateSystemShutdownEx        同InitiateSystemShutdown,扩展的功能是可以在系统
                    事件日志(事件号6006)中写入一个用户指定的双字节码

LockWorkStation            锁定工作站


系统关闭消息

WM_ENDSESSION

wParam

表示是否要终止程序。如果是TRUE,指令该程序终止,否则是FALSE

lParam

表示用户注销还是系统被关闭。如果此参数包含ENDSESSION_LOGOFF(lParam在这里是按位取值的)位,则表示是用户注销

Windows 2000 以及后续版本:如果lParam ==0,则表示系统被关闭。

程序收到此消息,如果wParam为TRUE,在完成消息处理后,程序随时都有可能被关闭。所以在此消息的处理过程里,应该尽量完成程序销毁前所需要进行的工作。

WM_QUERYENDSESSION

wParam

保留,未使用

lParam

同WM_ENDSESSION;

DefWindowProc默认返回:TRUE