对于不间断的Win32服务与用户交互,它必须打开用户的窗口站(“WinSta0”)和桌面(“默认”)。默认情况下,只有在LocalSystem帐户中运行的登录用户和Win 32服务被授予对用户的窗口站和桌面的访问权限。这意味着在其他帐户中运行的服务必须在打开交互式窗口站和桌面时模拟用户,或者由用户授予访问权限。
为了兼容可能支持每个用户多个用户和/或多个桌面的Windows NT的未来版本,用户的窗口站和桌面名称不应该被硬编码。客户端应用程序应将其窗口台和桌面的名称传递给服务,作为服务请求的一部分。
此代码示例在用户桌面上显示一条消息,以响应来自用户应用程序的RPC请求。请注意,此示例中的全局变量【dwGuiThreadId】也在注销处理示例中使用。如果显示消息框的线程在完成消息框后终止,则不需要保存和恢复线程的桌面。有必要恢复进程的窗口站。
DWORD dwGuiThreadId = 0;
INT
UserMessageBox(
RPC_BINDING_HANDLE h,
LPSTR lpszWindowStation,
LPSTR lpszDesktop,pl
LPSTR lpszText,
LPSTR lpszTitle,
UINT fuStyle)
{
DWORD dwThreadId;
HWINSTA hwinstaSave;
HDESK hdeskSave;
HWINSTA hwinstaUser;
HDESK hdeskUser;
int result;
/*
*确保连接到服务窗口站和桌面,以及
*保存他们的手柄。
*/
GetDesktopWindow();
hwinstaSave = GetProcessWindowStation();
dwThreadId = GetCurrentThreadId();
hdeskSave = GetThreadDesktop(dwThreadId);
/*
*模拟客户端并连接到用户
*窗台和桌面。
*/
RpcImpersonateClient(h);
hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
if (hwinstaUser == NULL) {
RpcRevertToSelf();
return 0;
}
SetProcessWindowStation(hwinstaUser);
hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
RpcRevertToSelf();
if (hdeskUser == NULL) {
SetProcessWindowStation(hwinstaSave);
CloseWindowStation(hwinstaUser);
return 0;
}
SetThreadDesktop(hdeskUser);
/*
*显示消息框。
*/
dwGuiThreadId = dwThreadId;
result = MessageBox(NULL, lpszText, lpszTitle, fuStyle);
dwGuiThreadId = 0;
/*
*恢复窗口站和桌面。
*/
SetThreadDesktop(hdeskSave);
SetProcessWindowStation(hwinstaSave);
CloseDesktop(hdeskUser);
CloseWindowStation(hwinstaUser);
return result;
}