Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9727200
  • 博文数量: 1227
  • 博客积分: 10026
  • 博客等级: 上将
  • 技术积分: 20273
  • 用 户 组: 普通用户
  • 注册时间: 2008-01-16 12:40
文章分类

全部博文(1227)

文章存档

2010年(1)

2008年(1226)

我的朋友

分类: C/C++

2008-03-14 14:17:54

下载本文示例代码
在Windows NT/2000/XP上编写程序时,有时会需要我们获取与当前调用线程关联的用户名和域名(domain),本文下面将示范在Windows NT/2000/XP环境里如何使用Win32 API有关安全的函数来获取用户名和域名。
    在Windows NT之前,一般都假设某个线程是运行在登录用户的帐号之下。但Windows NT问世以后,允许线程可以在多个安全上下文中运行,言下之意就是一个线程对多个用户。例如,在客户/服务器(C/S)应用中,服务器的某个线程可以通过 ImpersonateNamedPipeClient 函数模仿一个客户。在这种情况下,它运行在该客户端的用户上下文中。另一个运行在不同安全上下文中的线程例子是服务线程,它具备 NT AUTHORITY 域名和 SYSTEM 用户名,并且运行在本地系统账号之下。
    如果当前线程的用户名和域名两者你都需要,则必须首先调用 OpenThreadToken 打开与某个线程关联的存取令牌:
 if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken)) {

  if(GetLastError() == ERROR_NO_TOKEN) {
   //
   // 如果得不到线程令牌,则试图打开进程令牌。
   //
   if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken )) {
    ......
   }
  } 
  else {
      //
      // 存取线程令牌出错。
      //
      ......
  }
  
  ......      
 }
如果与当前线程关联的存取令牌不存在,则调用 OpenProcessToken 获取与当前进程关联的存取令牌。
一旦得到线程或进程的存取令牌,便可以调用 GetTokenInformation 函数从线程的存取令牌中获取用户安全标示,也就是 SID:
  bSuccess = GetTokenInformation(hToken, 
                                               TokenUser, 
                                               InfoBuffer, 
                                               cbInfoBuffer, 
                                               &cbInfoBuffer);
  if(!bSuccess) {
   ......
  }
  else {
   bRet = LookupAccountSid(NULL, ((PTOKEN_USER)InfoBuffer)->User.Sid, 
                                   UserName, 
                                   cchUserName, 
                                   DomainName, 
                                   cchDomainName, 
                                   &snu );
   if (!bRet) {
    ......
    CloseHandle(hToken);
    ......
   }
   else {
    // 显示得到的 用户名和域名
    
    SetDlgItemText(IDC_STATIC_USRN,UserName);
    SetDlgItemText(IDC_STATIC_DOMAIN,DomainName);
    ......
   }
   
  ...... 
  
 }
最后,调用 LookupAccountSid 函数获取与该SID关联的账号名和域名,详细实现细节请参考本文的例子代码。图一是例子程序运行的画面:


图一 获取用户名和域名例子程序

    在编写本文例子程序时,本来想写一个简单的控制台程序。但是很不幸,我碰到这样一个百思不得其解的问题:在控制台程序中调用LookupAccountSid函数,总是得到一个失败的返回,GetLastError() 函数指示的出错代码是14,也就是"存储器不足,无法完成此操作。"但在非控制台程序中调用是没有问题的。目前我还在继续琢磨这个问题。如果哪位已经知道其中的原因,不妨指点一二,以免我 再走弯路……。为了交流方便,我将控制台程序和非控制台程序的源代码都提供出来,以便参考。
    上面提到的几个32位函数不支持 Windows 9x。如果想存取Windows 95 或 Windows 98 系统中的用户名和交互用户的域信息,则必须调用16位LAN Manager 函数。详细实现细节请参考MSDN库的有关内容。
    注意:如果仅仅需要获取用户名,那么调用 GetUserName 足矣,这个函数支持 Windows 9x、Windows NT 以及 Windows 2000。在 Windows NT 和 Windows 2000 系统中,此函数首先检查调用线程是否具备专门的存取令牌,如果得到令牌,则返回与调用线程关联的用户名,否则,返回与调用进程关联的用户名。

最后,祝大家身体健康!编程愉快!
下载本文示例代码
阅读(1337) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~