我的玻璃盒子

[转载]Vista下服务与桌面互交

原文链接:http://www.cnblogs.com/lifeengines/archive/2008/08/26/1277054.html

     本来在Vista之前服务与桌面互交是一件很容易的事情,自从Vista把服务都挪到Session 0 中运行去而且不可以跨Session之后,问题就复杂了许多,有时候我就在想这些问题是否真的不得不解决而且似乎对于安全并未带来多大提升的更改总是让人 头疼,Google了一些文档,抄袭了不少代码我是如下实现的

 这个函数抄自winehq网站,顺便不得不说一下winehq的代码是很值得参考的

 1 BOOL WINAPI EnablePrivilege(LPSTR lpPrivilegeName, BOOL bEnable)
 2 {
 3     TOKEN_PRIVILEGES Privileges;
 4     HANDLE hToken;
 5     BOOL bResult;
 6     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
 7      return FALSE;
 8 
 9     Privileges.PrivilegeCount = 1;
10     Privileges.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0;
11 
12     if (!LookupPrivilegeValue(NULL, lpPrivilegeName,
13                             &Privileges.Privileges[0].Luid))
14     {
15      CloseHandle(hToken);
16      return FALSE;
17     }
18 
19     bResult = AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL);
20 
21     CloseHandle(hToken);
22 
23     return bResult;
24 }

 

EnablePrivilege用来提升本进程权限,因为我们的核心思路是用CreateProcessAsUser创建进程到需要互交的Session,

 

    //保证拥有权限
EnablePrivilege(SE_TCB_NAME, TRUE); 
    EnablePrivilege(SE_CHANGE_NOTIFY_NAME, TRUE);
    EnablePrivilege(SE_INCREASE_QUOTA_NAME, TRUE);
    EnablePrivilege(SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);

//获取当前进程的灵牌
        HANDLE hTokenThis = NULL;
        HANDLE hTokenDup 
= NULL;
        HANDLE hThisProcess 
= GetCurrentProcess();
        OpenProcessToken(hThisProcess, TOKEN_ALL_ACCESS, 
&hTokenThis);
//复制令牌
        DuplicateTokenEx(hTokenThis, MAXIMUM_ALLOWED,NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
//枚举所有Session,本来还有一个WTSGetActiveConsoleSessionId,不过这个函数在win2000下只有Server版本安装WTS才可以
        PWTS_SESSION_INFO pSInfo;
        DWORD pCInfo 
= 0;
        WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE,
0,1,&pSInfo,&pCInfo);
        DWORD dwSessionId 
= 0;
        
for (int i=0;i<pCInfo;i++)
        {
            
if (pSInfo[i].State == WTSActive)
            {
                dwSessionId 
= pSInfo[i].SessionId;
                
break;
            }
        }
        
//DWORD dwSessionId = WTSGetActiveConsoleSessionId();
//替换令牌,关键地方,我们并不需要以Session用户创建进程,只需要替换令牌就可以了
        SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD));

        STARTUPINFO si 
= {0};
        PROCESS_INFORMATION pi 
= {0};
        si.cb 
= sizeof(si);
        si.lpDesktop 
= "WinSta0\\Default";
        DWORD dwCreationFlag 
= NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
        
char    pPath[MAX_PATH*2];
        GetModuleFileName(NULL,pPath,
sizeof(pPath));
        strcat(pPath,
" -work");
        LPVOID pEnv;
        CreateEnvironmentBlock(
&pEnv,hTokenDup,FALSE);
        
if (!CreateProcessAsUser(hTokenDup,NULL,pPath,NULL,NULL,FALSE,dwCreationFlag,pEnv,NULL,&si,&pi))
        {
// 
//             int p = GetLastError();
//             p = 0;
        }
        WaitForSingleObject(pi.hProcess,INFINITE);
        CloseHandle(hTokenDup);
        CloseHandle(hTokenThis);

这样我们的程序就可以和桌面互交了,这只是核心,其余牵涉多用户切换这些还需要另外考虑

posted on 2009-01-06 16:59 深蓝色系统 阅读(954) 评论(0)  编辑 收藏 引用 所属分类: Windows开发


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

统计

常用链接

留言簿(75)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜