获取当前用户的上次登录

时间:2010-07-30 13:20:44

标签: c windows authentication

我正在尝试让当前用户上次登录。我可能是本届会议,也可能是之前的会议 我正在调用GetUserName()来获取当前用户名。我将其提供给NetUserGetInfo()以尝试获取上次登录时间。所有这些都失败,错误2221(未找到用户)。当我尝试使用“管理员”时,它可以工作。即使我对用户名进行硬编码,也会返回2221.这就是我正在使用的内容:

nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);

如何获得当前用户的上次登录时间?

谢谢,代码随时欢迎。

以下是我目前正在使用的完整代码:

DWORD dwLevel = 2;
NET_API_STATUS nStatus;
LPTSTR sStringSid = NULL;
LPUSER_INFO_0 pBuf = NULL;
LPUSER_INFO_2 pBuf2 = NULL;
WCHAR UserName[256];
DWORD nUserName = sizeof(UserName); 

if(GetUserName(UserName, &nUserName))
{
    printf("information for %ls\n", UserName);
    nStatus = NetUserGetInfo(NULL, UserName, dwLevel, (LPBYTE *) & pBuf);
    if (nStatus == NERR_Success) 
    {
        pBuf2 = (LPUSER_INFO_2) pBuf;
        printf("\tUser account name: %ls\n", pBuf2->usri2_name);
        printf("\tLast logon (seconds since January 1, 1970 GMT): %d\n", pBuf2->usri2_last_logon);
        printf("\tLast logoff (seconds since January 1, 1970 GMT): %d\n", pBuf2->usri2_last_logoff);
    }
    else
        fprintf(stderr, "NetUserGetinfo failed with error: %d\n", nStatus);

    if (pBuf != NULL)
        NetApiBufferFree(pBuf);
}

1 个答案:

答案 0 :(得分:7)

您可以尝试将其他级别用作2,例如11。

您可以尝试LsaGetLogonSessionData(请参阅http://msdn.microsoft.com/en-us/library/aa378290.aspx)。结构SECURITY_LOGON_SESSION_DATA有很多信息可以对你有所帮助。 LUID LsaGetLogonSessionData的第一个参数GetTokenInformation可以TokenStatistics获得AuthenticationId并获取TOKEN_STATISTICS结构的NetUserGetInfo字段。< / p>

更新:我仔细阅读了您的代码,现在我看到了您的主要错误。函数NetUserGetInfo非常陈旧。它存在于Windows NT 3.1之前的时间。 Microsoft现在命名为“网络管理”的一组功能名称为“LAN Manager API”。所有功能都是在没有本地登录的时候引入的。因此,您可以使用NetGetDCName将NULL作为第一个参数仅在域控制器上。因此,如果您使用域帐户登录,则应调用NetGetAnyDCNameDsGetDcName或更好NetUserGetInfo以获取域控制器的名称并使用此名称(以两个反斜杠开头)作为nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf); 的第一个参数。如果您使用本地工作站帐户登录,您的程序应该可以使用,但该帐户似乎必须是UNICODE字符串,如L“Administrator”而不是“Administrator”。顺便说一句,如果我在Windows 7 64位计算机上本地登录,您的程序可以毫无问题地工作。代码

LsaGetLogonSessionData

也有效。

我再说一遍,在我看来,获得用户上次登录的最佳方式是使用LSA(本地安全机构)API,如LsaGetLogonSessionData。承诺我为你写了一个代码示例,演示了如何在C:

中使用#include <windows.h> #include <Ntsecapi.h> #include <Sddl.h> #include <tchar.h> #include <stdio.h> //#include <ntstatus.h> #include <malloc.h> #include <strsafe.h> #pragma comment (lib, "Secur32.lib") #pragma comment (lib, "strsafe.lib") // The following constant may be defined by including NtStatus.h. #ifndef STATUS_SUCCESS #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #endif // The LSA authentication functions are available in Unicode only. BOOL GetLogonLUID (LUID *pLuid) { BOOL bSuccess; HANDLE hThread = NULL; DWORD cbReturnLength; TOKEN_STATISTICS ts; __try { bSuccess = OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hThread); // TOKEN_QUERY_SOURCE if (!bSuccess) __leave; cbReturnLength = sizeof(TOKEN_STATISTICS); bSuccess = GetTokenInformation (hThread, TokenStatistics, &ts, sizeof(TOKEN_STATISTICS), &cbReturnLength); if (bSuccess) *pLuid = ts.AuthenticationId; } __finally { if (hThread) CloseHandle (hThread); } return bSuccess; } void PrintUnicodeString (LPCTSTR pszPrefix, LSA_UNICODE_STRING lsaString) { if (lsaString.MaximumLength >= lsaString.Length + sizeof(WCHAR) && lsaString.Buffer[lsaString.Length/sizeof(WCHAR)] == L'\0') _tprintf (TEXT("%s: %ls\n"), pszPrefix, lsaString.Buffer); else if (lsaString.Length <= STRSAFE_MAX_CCH * sizeof(TCHAR)) { LPWSTR sz = (LPWSTR) _alloca (lsaString.Length + sizeof(WCHAR)); StringCbCopyNW (sz, lsaString.Length + sizeof(WCHAR), lsaString.Buffer, lsaString.Length); _tprintf (TEXT("%s: %ls\n"), pszPrefix, sz); } } void PrintLogonType (SECURITY_LOGON_TYPE type) { if (type < Interactive || type > CachedUnlock) // This is used to specify an undefied logon type _tprintf (TEXT("LogonType: UndefinedLogonType\n")); else { static LPTSTR szTypes[] = { TEXT("Interactive"), // Interactively logged on (locally or remotely) TEXT("Network"), // Accessing system via network TEXT("Batch"), // Started via a batch queue TEXT("Service"), // Service started by service controller TEXT("Proxy"), // Proxy logon TEXT("Unlock"), // Unlock workstation TEXT("NetworkCleartext"), // Network logon with cleartext credentials TEXT("NewCredentials"), // Clone caller, new default credentials TEXT("RemoteInteractive"), // Remote, yet interactive. Terminal server TEXT("CachedInteractive"), // Try cached credentials without hitting the net. // The types below only exist in Windows Server 2003 and greater TEXT("CachedRemoteInteractive"), // Same as RemoteInteractive, this is used internally for auditing purpose TEXT("CachedUnlock") // Cached Unlock workstation }; _tprintf (TEXT("LogonType: %s\n"), szTypes[(int)type-Interactive]); } } void PrintFilefime (LPCTSTR pszPrefix, const FILETIME *lpFileTime) { SYSTEMTIME st; FILETIME ft; BOOL bSuccess; TCHAR szTime[1024], szDate[1024]; bSuccess = FileTimeToLocalFileTime (lpFileTime, &ft); if (!bSuccess) return; bSuccess = FileTimeToSystemTime (&ft, &st); if (!bSuccess) return; if (GetDateFormat (LOCALE_USER_DEFAULT, // or LOCALE_CUSTOM_UI_DEFAULT DATE_SHORTDATE, &st, NULL, szDate, sizeof(szDate)/sizeof(TCHAR)) > 0) { if (GetTimeFormat (LOCALE_USER_DEFAULT, // or LOCALE_CUSTOM_UI_DEFAULT 0, &st, NULL, szTime, sizeof(szTime)/sizeof(TCHAR)) > 0) { _tprintf (TEXT("%s: %s, %s\n"), pszPrefix, szDate, szTime); } } } int main() { LUID LogonLuid; // LOGONID_CURRENT PSECURITY_LOGON_SESSION_DATA pLogonSessionData = NULL; LPWSTR pszSid = NULL; NTSTATUS ntStatus; GetLogonLUID (&LogonLuid); __try { ntStatus = LsaGetLogonSessionData (&LogonLuid, &pLogonSessionData); if (ntStatus == STATUS_SUCCESS) { if (pLogonSessionData->UserName.Length) PrintUnicodeString (TEXT("UserName"), pLogonSessionData->UserName); if (pLogonSessionData->LogonDomain.Length) PrintUnicodeString (TEXT("LogonDomain"), pLogonSessionData->LogonDomain); if (pLogonSessionData->AuthenticationPackage.Length) PrintUnicodeString (TEXT("AuthenticationPackage"), pLogonSessionData->AuthenticationPackage); PrintLogonType ((SECURITY_LOGON_TYPE)pLogonSessionData->LogonType); _tprintf (TEXT("Session: %d\n"), pLogonSessionData->Session); if (ConvertSidToStringSidW (pLogonSessionData->Sid, &pszSid)) _tprintf (TEXT("Sid: %ls\n"), pszSid); if (pLogonSessionData->LogonTime.QuadPart) PrintFilefime (TEXT("LogonTime"), (const FILETIME *)&pLogonSessionData->LogonTime); if (pLogonSessionData->LogonServer.Length) PrintUnicodeString (TEXT("LogonServer"), pLogonSessionData->LogonServer); if (pLogonSessionData->DnsDomainName.Length) PrintUnicodeString (TEXT("DnsDomainName"), pLogonSessionData->DnsDomainName); if (pLogonSessionData->Upn.Length) PrintUnicodeString (TEXT("Upn"), pLogonSessionData->Upn); // one can dump more information like HomeDirectory, ProfilePath and so on // if _WIN32_WINNT >= 0x0600 and user login a domain } } __finally { if (pLogonSessionData) LsaFreeReturnBuffer(pLogonSessionData); if (pszSid) pszSid = (LPTSTR)LocalFree (pszSid); } }
{{1}}