WTS APIs(Windows终端服务API)获取进程信息

 Windows XP 有一个新特性叫做“快速用户转换——Fast User Switching”,这个特性允许多个用户同时在一台机器上登陆。当一个用户登陆后,另一个用户启动的进程仍然能够运行。这个神奇的特性所倚仗的是 WTS APIs。如果你想了解更多有关 WTS 的内容,可以参考 MSJ Oct99 的一篇文章:“ Windows NT和 Windows 2000 终端服务APIs介绍”,作者是 Frank Kim。
  Windows XP为每一个登陆用户创建一个WTS会话(Session)。每个运行进程总是与这样一个Session关联。Windows XP的任务管理器允许你列出进程清单,不论是针对所有会话的还是仅仅针对自己的会话,任务管理器对话框的进程标签中有一个"显示所有用户的进程"复选框可以对此进行选择。(如图十一所示):



图十一 任务管理其的进程列表


  如果你想了解某个进程隶属的 session ID,可以调用 kernel32.dll 输出的一个 API 函数 ProcessIdToSessionId。给定一个进程的ID,他返回相应的 session ID。有趣的是这个 API 函数不是由 wtsapi32.dll 输出的,而是出自于 kernel32.dll,前者是所有 Windows 终端服务 APIs 的输出动态库。实际上,即使 Windows 终端服务没有运行起来,Windows 2000 和 Windows XP 都将 session ID 存储在 PEB 中。
  注意 Windows NT 既不在 PEB 中存储 session ID,也不从 kernel32.dll 中输出 ProcessIdToSessionId 函数。当你调用 ProcessIdToSessionId,而 WTS 又没有运行,这时其返回值总是0。
  除了允许你列出打开的会话之外,WTS 还有一个 API 用于枚举运行的进程,其实现方式与 PSAPI 和 TOOLHELP32 的实现方式是不同的。我写了一个类 CWTSWrapper 来打包 WTS 中与进程和会话有关的函数,以便避免与 wtsapi32.dll 进行静态链接。这个类的实现细节请参考下载的源代码,见 common 目录的 wrappers.cpp 文件。用 CWTSWrapper 很容易构造象 ProcessXP 这样的控制台应用程序。下面是ProcessXP 程序的输出,它列出了与登陆用户对应的打开的会话以及会话项下的运行进程。ProcessXP 程序的输出如下:
3 open sessions
----------------------------
ID State Window Station
----------------------------
0 (WTSActive) Console [Administrator]
1 (WTSDisconnected) [standard]
2 (WTSDisconnected) [Player]

30 running processes
----------------------------
0 0 ?
0 4 System //NT AUTHORITY/SYSTEM
0 388 smss.exe //NT AUTHORITY/SYSTEM
0 600 csrss.exe //NT AUTHORITY/SYSTEM
0 632 winlogon.exe //NT AUTHORITY/SYSTEM
0 676 services.exe //NT AUTHORITY/SYSTEM
0 688 lsass.exe //NT AUTHORITY/SYSTEM
0 856 svchost.exe //NT AUTHORITY/SYSTEM
0 968 svchost.exe //NT AUTHORITY/SYSTEM
0 1160 svchost.exe //NT AUTHORITY/NETWORK SERVICE
0 1192 svchost.exe //NT AUTHORITY/LOCAL SERVICE
0 1252 spoolsv.exe //NT AUTHORITY/SYSTEM
0 1888 explorer.exe //MACHINE/Administrator
0 2004 msmsgs.exe //MACHINE/Administrator
0 104 svchost.exe //NT AUTHORITY/SYSTEM
1 1496 csrss.exe //NT AUTHORITY/SYSTEM
1 1172 winlogon.exe //NT AUTHORITY/SYSTEM
1 1640 explorer.exe //MACHINE/standard
1 1900 ctfmon.exe //MACHINE/standard
1 352 notepad.exe //MACHINE/standard
1 1896 freecell.exe //MACHINE/standard
2 416 csrss.exe //NT AUTHORITY/SYSTEM
2 268 winlogon.exe //NT AUTHORITY/SYSTEM
2 1784 explorer.exe //MACHINE/Player
0 1820 msiexec.exe //NT AUTHORITY/SYSTEM
2 1544 ctfmon.exe //MACHINE/Player
2 1632 msmsgs.exe //MACHINE/Player
2 1268 wordpad.exe //MACHINE/Player
0 1696 wuauclt.exe //MACHINE/Administrator
0 1996 ProcessXP.exe //MACHINE/Administrator 

  从上面的输出可以看出,名为 MACHINE 的机器上打开的会话有三各。第一个会话的 ID 为0,状态为活动(WTSActive 因为它就是运行中的 ProcessXP 所在的会话),产生这个会话的登陆用户为 Administrator。第二个会话的ID是1,处于断开状态(WTSDisconnected),产生这个会话的用户为标准用户,此用户启动了 Notepad 和 Freecell 程序,用户Player打开了会话2,并运行WordPad,但目前状态是断开的。
  ProcessXP 的源代码包含在本文可下载的压缩包中。WTS 有一个与注册表类似特性,那就是允许你获取另外一台机器的信息。这就是为什么WTS枚举 APIs 函数的第一个参数都是一个服务器句柄。WTS_CURRENT_SERVER_HANDLE 用于当前的机器。第二个参数是保留参数,值应该为0。第三个参数希望的版本,其值应该是1。最后两个参数用于存放返回的信息。一个用于存放会话数或进程数。另一个是结构数组的指针,结构可以是描述会话信息的结构,也可以是描述进程信息的结构。就看你是使用哪个枚举API,是枚举会话还是枚举进程。因为数组的存储空间是由 WTS 分配的,你必须要记住用 WTSFreeMemory 释放这个空间。
下面是描述会话的结构:WTS_SESSION_INFO:

typedef struct _WTS_SESSION_INFO
{
    DWORD SessionId;
    LPTSTR pWinStationName;
    WTS_CONNECTSTATE_CLASS State;
} WTS_SESSION_INFO, * PWTS_SESSION_INFO;

  结构中除了会话的 SessionId,还有会话名 pWinStationName,当前会话的名字是“console”,而其它的会话是无名的。当前的会话状态为 WTSActive,其它则为 WTSDisconnected。

下面是描述进程的结构 WTS_PROCESS_ INFO:

typedef struct _WTS_PROCESS_INFO 
{
    DWORD SessionId;
    DWORD ProcessId;
    LPTSTR pProcessName;
    PSID pUserSid;
} WTS_PROCESS_INFO, * PWTS_PROCESS_INFO;

  SessionId 与 ProcessIdToSessionId 所要找的值一样,ProcessId 不用说了,是进程ID。最后一个成员 pUserSid 指向安全标示符,描述用户账号,用户正是在这个账号下运行进程。使用 LookupAccountSid,你可以获得从 pUserSid 中获得用户名。这个信息已经可以通过 CProcess 类中的 GetProcessOwner 获得,但它是通过进程记号(token),而不是通过 WTS。某些情况下,即便由 WTSEnumerateProcesses 控制对它的提供,要想获得进程记号也是不可能的,这就是在 Windows XP 环境下要用 WTS API 而不用 PSAPI 或 TOOLHELP32 的缘故

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值