程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 如何獲取線程關聯用戶名和域名

如何獲取線程關聯用戶名和域名

編輯:關於VC++

在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 系統中,此函數首先檢查調用線程是否具備專門的存取令牌,如果得到令牌,則返回與調用線程關聯的用戶名,否則,返回與調用進程關聯的用戶名。

最後,祝大家身體健康!編程愉快!

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved