먼저 로컬 보안 정책에서 계정 잠금 기간 값을 가져온다.
#include <windows.h>
#include <LM.h>
#include <iostream>
#pragma comment(lib, "netapi32.lib")
int main() {
USER_MODALS_INFO_3* userModalsInfo;
NET_API_STATUS status = NetUserModalsGet(NULL, 3, (LPBYTE*)&userModalsInfo);
if (status == NERR_Success) {
std::wcout << L"잠금 시간: " << userModalsInfo->usrmod3_lockout_duration / 60 << L"분" << std::endl;
NetApiBufferFree(userModalsInfo);
} else {
std::cerr << "Error: " << status << std::endl;
}
return 0;
}
아래 코드로 윈도우 시스템 이벤트에서 잠금 이벤트 ID 4740을 검색한다.
#include <iostream>
#include <Windows.h>
#include <winevt.h>
#pragma comment(lib, "wevtapi.lib")
void QueryEventLog()
{
// 열려는 로그의 이름 (Security 로그)
LPCWSTR logName = L"Security";
// 검색할 쿼리 - Event ID 4740
LPCWSTR query = L"*[System[(EventID=4740)]]";
EVT_HANDLE hResults = EvtQuery(nullptr, logName, query, EvtQueryReverseDirection | EvtQueryTolerateQueryErrors);
if (!hResults) {
std::cerr << "EvtQuery failed with error code: " << GetLastError() << std::endl;
return;
}
EVT_HANDLE hEvent;
DWORD dwReturned = 0;
while (EvtNext(hResults, 1, &hEvent, INFINITE, 0, &dwReturned)) {
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
// 이벤트 텍스트 데이터를 읽기 위해 필요한 버퍼 크기를 확인
EvtRender(nullptr, hEvent, EvtRenderEventXml, dwBufferSize, nullptr, &dwBufferUsed, &dwPropertyCount);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
std::wstring buffer(dwBufferUsed / sizeof(wchar_t), L'\0');
if (EvtRender(nullptr, hEvent, EvtRenderEventXml, dwBufferUsed, &buffer[0], &dwBufferUsed, &dwPropertyCount)) {
// 이벤트 XML 출력
std::wcout << L"Event: " << buffer << std::endl;
}
}
EvtClose(hEvent);
}
if (GetLastError() != ERROR_NO_MORE_ITEMS) {
std::cerr << "EvtNext failed with error code: " << GetLastError() << std::endl;
}
EvtClose(hResults);
}
int main()
{
QueryEventLog();
return 0;
}
검색후 마지막 이벤트 XML값에서 이벤트 시점과 잠금 기간을 더한 값을 현재 시간과 비교해서 이전이면 잠금 상태라고 판단한다.
물론 이벤트가 없으면 잠금 상태가 아니다.
물론 이벤트가 없으면 잠금 상태가 아니다.