Active Directory includes an attribute named lastLogon which tells you the last time a user or computer logged on, but last logon time will not be accurate in case you have more than one domain controllers, why, this is because the lastLogon attribute is not replicated from one domain controller to another. Suppose you have two domain controllers: A and B, a new user logs on to domain controller A. You now write a piece of code to request the last logon time for the new user, and the code happens to connect to domain controller B. Oddly enough, the code will tell you that the user has never logged on, even though you know for a fact that the user is logged on right now.
To determine the last logon time for a user, the first solution is that you have to retrieve the lastLogon attribute from every domain controller in the domain and then compare all those values to determine the true last logon time.
Since Windows Server 2003, a brand-new attribute named lastLogonTimestamp is added in the schema. This attribute also keeps track of the last time a user logged on to the domain, moreover, this new attribute is replicated from one domain controller to another. So to know the last time a user logged on, you can just write code to connect to any domain controller and query the value of this attribute.
The lastLogonTimestamp is stored as a 64-bit integer in Windows Server 2003. When you query the lastLogonTimestamp you don’t get back a date-time like May 15, 2008 8:05 AM. Instead, you get back the number of 100-nanosecond intervals that passed between January 1, 1601 and the time the user last logged on. Consequently your code will be involved in taking that weird 64-bit integer value and converting it to a date and time.
The following C++ code shows you how to return the last logon time for a user in a Windows Server 2008 domain.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <comdef.h>
#include <activeds.h>
#include <atlbase.h>
#include <atlconv.h>
#include <Iads.h>
#include <time.h>
#using <mscorlib.dll>
using namespace System;
int main()
{
HRESULT hResult = CoInitialize(NULL);
IADs *pObject;
USES_CONVERSION;
//Replace the following information with yours
LPWSTR pathName = L"LDAP://your AD pathname";
LPWSTR userName = L"Your user name";
LPWSTR pwd= L"password";
hResult = ADsOpenObject(pathName, userName, pwd, ADS_SECURE_AUTHENTICATION, IID_IADs, (void**) &pObject);
VARIANT var;
VariantInit(&var);
var.vt = VT_I4;
hResult = pObject->Get(L"lastLogonTimestamp", &var);
FILETIME ft;
ft.dwHighDateTime = var.pvarVal->cyVal.Hi;
ft.dwLowDateTime = var.pvarVal->cyVal.Lo;
SYSTEMTIME st;
FileTimeToSystemTime(&ft, &st);
TIME_ZONE_INFORMATION tz;
SYSTEMTIME localst;
GetTimeZoneInformation(&tz);
SystemTimeToTzSpecificLocalTime(&tz, &st, &localst);
printf("Last Logon Time Stamp: %d/%d/%d %d:%d:%d\n", localst.wYear,localst.wMonth, localst.wDay, localst.wHour, localst.wMinute, localst.wSecond);
pObject->Release();
CoUninitialize();
return 0;
}