Mr *_*eph 4 c windows authentication
我试图让当前用户上次登录.我可能是当前的会议,也可能是之前的会议.
我正在调用GetUserName()来获取当前用户名.我将其提供给NetUserGetInfo()以尝试获取上次登录时间.所有这些都失败,错误2221(未找到用户).当我尝试使用"管理员"时,它可以工作.即使我对用户名进行硬编码,也会返回2221.这就是我使用的内容:
nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);
Run Code Online (Sandbox Code Playgroud)
如何获得当前用户的上次登录时间?
谢谢,代码随时欢迎.
这是我目前使用的完整代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
你可以尝试使用其他级别为2,例如11.
您可以尝试LsaGetLogonSessionData(请参阅http://msdn.microsoft.com/en-us/library/aa378290.aspx).该结构SECURITY_LOGON_SESSION_DATA有很多信息,对您有所帮助.的LUID(第一个参数LsaGetLogonSessionData),你可以从GetTokenInformation使用TokenStatistics和获得AuthenticationId基于场TOKEN_STATISTICS结构.
更新:我仔细阅读了你的代码,现在我看到了你的主要错误.功能NetUserGetInfo很老.它存在于Windows NT 3.1之前的时间.Microsoft现在命名为"网络管理"的一组功能名称为"LAN Manager API".所有功能都是在没有本地登录的时候引入的.因此,您只能在域控制器上使用NetUserGetInfoNULL作为第一个参数.因此,如果您使用域帐户登录,则应该调用,或者更好地获取域控制器的名称,并使用此名称(以两个反斜杠开头)作为第一个参数.如果您使用本地工作站帐户登录,您的程序应该可以工作,但帐户似乎我必须是UNICODE字符串NetGetDCNameNetGetAnyDCNameDsGetDcNameNetUserGetInfo像L"管理员"而不是"管理员".顺便说一句,如果我在Windows 7 64位计算机上本地登录,您的程序可以毫无问题地工作.代码
nStatus = NetUserGetInfo(NULL, L"administrator", dwLevel, (LPBYTE *) & pBuf);
Run Code Online (Sandbox Code Playgroud)
也有效.
我再说一遍,在我看来,获得用户上次登录的最佳方式是使用LSA(本地安全机构)API LsaGetLogonSessionData.承诺我为你写了一个代码示例,展示如何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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7092 次 |
| 最近记录: |