概述: AD 调用函数中相关函数的使用整理

0x01 时间转换

相关链接:

  1. FileTimeToSystemTime 函数 (timezoneapi.h) - Win32 apps | Microsoft Learn
  2. 如何将 Active Directory 中的日期/时间属性转换为标准时间格式 - Windows Server | Microsoft Learn
if (_wcsicmp(col.pszAttrName, L"lastLogon") == 0)
{
    ADS_UTC_TIME tm = col.pADsValues->UTCTime;
    SYSTEMTIME monTS;
    if (FileTimeToSystemTime(reinterpret_cast<PFILETIME>(&tm), &monTS) != FALSE)
    {
        CStringA sTime;
        sTime.Format("%04d-%02d-%02d %02d:%02d:%02d", monTS.wYear, monTS.wMonth, monTS.wDay, monTS.wHour, monTS.wMinute, monTS.wSecond);
 
        uAccount.strLastLogon = sTime;
    }
    uAccount.tmLastLogon = col.pADsValues->Timestamp.WholeSeconds;
}

0x02 封装函数

typedef struct _USERACCOUNT
{
	std::string     UserName;               // 用户名
	std::string     strDomain;              // 所在域
	std::string     strGroup;               // 所在组
	std::string     strSID;                 // SID
	std::string     strHomePath;            // home 
	bool        	bDisabled;              // 是否禁用
	bool        	bAdmin;                 // 是否管理员
	__time64_t  	tmLastLogon;            // 最后登录时间
	std::string		strLastLogon;            // 最后登录时间
	unsigned int    dwPwStatus;             // 密码状态, 已设置 1, 空密码 2, 已锁定 3 域用户:1 需要密码 2 无需密码
	std::string    	strPwdChangeTime;       // 密码修改时间
	std::string    	strPwdExpireTime;       // 密码过期时间
	std::string    	strAccountType;          // 1 本地账户,2全局账户 3 域用户
	std::string    	strIsDomain;             // 1 是,2不是
}UserAccount;
 
inline void ConvertColToUAStruct(const ADS_SEARCH_COLUMN& col, UserAccount& uAccount)
{
	DWORD x = 0;
	if (col.dwADsType == ADSTYPE_CASE_IGNORE_STRING)
	{
		for (x = 0; x < col.dwNumValues; x++) {
			if (_wcsicmp(col.pszAttrName, L"sAMAccountName") == 0)
			{
				uAccount.UserName = col.pADsValues->CaseIgnoreString;
			}
		}
	}
	else if (col.dwADsType == ADSTYPE_INTEGER)
	{
		if (_wcsicmp(col.pszAttrName, L"userAccountControl") == 0)
		{
			uAccount.bDisabled = ((col.pADsValues->Integer & ADS_UF_ACCOUNTDISABLE) == ADS_UF_ACCOUNTDISABLE) ? TRUE : FALSE;
 
			if ((ADS_UF_PASSWD_NOTREQD & col.pADsValues->Integer) == ADS_UF_PASSWD_NOTREQD)
			{
				uAccount.dwPwStatus = PASSWORD_TYPE_EMPTY;
			}
			else if ((ADS_UF_LOCKOUT & col.pADsValues->Integer) == ADS_UF_LOCKOUT)
			{
				uAccount.dwPwStatus = PASSWORD_TYPE_LOCK;
			}
			else
			{
				uAccount.dwPwStatus = PASSWORD_TYPE_REQ;
			}
		}
		else if (_wcsicmp(col.pszAttrName, L"ms-DS-User-Account-Control-Computed") == 0)
		{
			uAccount.bDisabled = ((col.pADsValues->Integer & ADS_UF_ACCOUNTDISABLE) == ADS_UF_ACCOUNTDISABLE) ? TRUE : FALSE;
 
			if ((ADS_UF_LOCKOUT & col.pADsValues->Integer) == ADS_UF_LOCKOUT)
			{
				uAccount.dwPwStatus = PASSWORD_TYPE_LOCK;
			}
		}
		else if (_wcsicmp(col.pszAttrName, L"maxPwdAge") == 0)
		{
			CStringW strTime;
			DWORD Days = col.pADsValues->LargeInteger.QuadPart / 1000 / 1000 / 1000 / 60 / 60 / 24;
			strTime.Format(L"%d day(s)", Days);
			uAccount.strPwdExpireTime = strTime;
		}
		else if (_wcsicmp(col.pszAttrName, L"lastLogonTimestamp") == 0)
		{
			ADS_LARGE_INTEGER strValue = col.pADsValues->LargeInteger;
			uAccount.tmLastLogon = strValue.QuadPart;
		}
	}
	else if (col.dwADsType == ADSTYPE_LARGE_INTEGER)
	{
		for (x = 0; x < col.dwNumValues; x++)
		{
			if (_wcsicmp(col.pszAttrName, L"lastLogon") == 0)
			{
				ADS_UTC_TIME tm = col.pADsValues->UTCTime;
				SYSTEMTIME monTS;
				if (FileTimeToSystemTime(reinterpret_cast<PFILETIME>(&tm), &monTS) != FALSE)
				{
					CStringA sTime;
					sTime.Format("%04d-%02d-%02d %02d:%02d:%02d", monTS.wYear, monTS.wMonth, monTS.wDay, monTS.wHour, monTS.wMinute, monTS.wSecond);
 
					uAccount.strLastLogon = sTime;
				}
				uAccount.tmLastLogon = col.pADsValues->Timestamp.WholeSeconds;
			}
			else if (_wcsicmp(col.pszAttrName, L"pwdLastSet") == 0)
			{
				ADS_UTC_TIME tm = col.pADsValues->UTCTime;
				SYSTEMTIME monTS;
				if (FileTimeToSystemTime(reinterpret_cast<PFILETIME>(&tm), &monTS) != FALSE)
				{
					CStringA sTime;
					sTime.Format("%04d-%02d-%02d %02d:%02d:%02d", monTS.wYear, monTS.wMonth, monTS.wDay, monTS.wHour, monTS.wMinute, monTS.wSecond);
 
					uAccount.strPwdChangeTime = sTime;
				}
			}
		}
	}
	else if (col.dwADsType == ADSTYPE_OCTET_STRING)
	{
		for (x = 0; x < col.dwNumValues; x++)
		{
			if (_wcsicmp(col.pszAttrName, L"objectSid") == 0)
			{
				PSID pObjectSID = NULL;
				LPWSTR lpSID = NULL;
				pObjectSID = (PSID)(col.pADsValues[x].OctetString.lpValue);
				// Convert SID to string.
				ConvertSidToStringSidW(pObjectSID, &lpSID);
				uAccount.strSID = lpSID;
 
				if (lpSID)
				{
					LocalFree(lpSID);
				}
			}
		}
	}
	else if (col.dwADsType == ADSTYPE_BOOLEAN)
	{
		for (x = 0; x < col.dwNumValues; x++) {
			if (_wcsicmp(col.pszAttrName, L"isCriticalSystemObject") == 0)
			{
				uAccount.bAdmin = col.pADsValues->Boolean;
			}
		}
	}
}