static void test_oldest(void) { HANDLE handle; BOOL ret; DWORD oldest; const char backup[] = "backup.evt"; SetLastError(0xdeadbeef); ret = GetOldestEventLogRecord(NULL, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); SetLastError(0xdeadbeef); oldest = 0xdeadbeef; ret = GetOldestEventLogRecord(NULL, &oldest); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); ok(oldest == 0xdeadbeef, "Expected oldest to stay unchanged\n"); handle = OpenEventLogA(NULL, "Application"); SetLastError(0xdeadbeef); ret = GetOldestEventLogRecord(handle, NULL); ok(!ret, "Expected failure\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); oldest = 0xdeadbeef; ret = GetOldestEventLogRecord(handle, &oldest); ok(ret, "Expected success\n"); ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n"); CloseEventLog(handle); /* Make a backup eventlog to work with */ if (create_backup(backup)) { handle = OpenBackupEventLogA(NULL, backup); todo_wine ok(handle != NULL, "Expected a handle\n"); /* Does GetOldestEventLogRecord work with backup eventlogs? */ oldest = 0xdeadbeef; ret = GetOldestEventLogRecord(handle, &oldest); todo_wine { ok(ret, "Expected success\n"); ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n"); } CloseEventLog(handle); DeleteFileA(backup); } }
/* Start the event logging for each el */ int startEL(char *app, os_el *el) { DWORD NumberOfRecords = 0; /* Open the event log */ el->h = OpenEventLog(NULL, app); if (!el->h) { merror(EVTLOG_OPEN, ARGV0, app); return (-1); } el->name = app; if (GetOldestEventLogRecord(el->h, &el->record) == 0) { /* Unable to read oldest event log record */ merror(EVTLOG_GETLAST, ARGV0, app); CloseEventLog(el->h); el->h = NULL; return (-1); } if (GetNumberOfEventLogRecords(el->h, &NumberOfRecords) == 0) { merror(EVTLOG_GETLAST, ARGV0, app); CloseEventLog(el->h); el->h = NULL; return (-1); } if (NumberOfRecords <= 0) { return (0); } return ((int)NumberOfRecords); }
/** int startEL(char *app, os_el *el) * Starts the event logging for each el */ int startEL(char *app, os_el *el) { /* Opening the event log */ el->h = OpenEventLog(NULL, app); if(!el->h) { return(0); } el->name = app; GetOldestEventLogRecord(el->h, &el->record); return(1); }
/* * Returns the record number of the oldest record (not necessarily 1). * * TLVs: * * req: TLV_TYPE_EVENT_HANDLE - The event log handle */ DWORD request_sys_eventlog_oldest(Remote * remote, Packet * packet) { Packet * response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; HANDLE hEvent = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_EVENT_HANDLE); DWORD oldest; if(GetOldestEventLogRecord(hEvent, &oldest) == 0) { result = GetLastError(); } else { packet_add_tlv_uint(response, TLV_TYPE_EVENT_RECORDNUMBER, oldest); } packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* open event logger and return number of records */ static int zbx_open_eventlog(LPCTSTR wsource, HANDLE *eventlog_handle, zbx_uint64_t *FirstID, zbx_uint64_t *LastID) { const char *__function_name = "zbx_open_eventlog"; wchar_t reg_path[MAX_PATH]; HKEY hk = NULL; DWORD dwNumRecords, dwOldestRecord; int ret = FAIL; zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); *eventlog_handle = NULL; /* Get path to eventlog */ StringCchPrintf(reg_path, MAX_PATH, EVENTLOG_REG_PATH TEXT("%s"), wsource); if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hk)) goto out; RegCloseKey(hk); if (NULL == (*eventlog_handle = OpenEventLog(NULL, wsource))) /* open log file */ goto out; if (0 == GetNumberOfEventLogRecords(*eventlog_handle, &dwNumRecords) || 0 == GetOldestEventLogRecord(*eventlog_handle, &dwOldestRecord)) { CloseEventLog(*eventlog_handle); *eventlog_handle = NULL; goto out; } *FirstID = dwOldestRecord; *LastID = dwOldestRecord + dwNumRecords - 1; zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s FirstID:" ZBX_FS_UI64 " LastID:" ZBX_FS_UI64 " numIDs:%lu", __function_name, zbx_result_string(ret), *FirstID, *LastID, dwNumRecords); ret = SUCCEED; out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/* open event logger and return number of records */ static int zbx_open_eventlog(LPCTSTR wsource, HANDLE *eventlog_handle, long *pNumRecords, long *pLatestRecord) { const char *__function_name = "zbx_open_eventlog"; TCHAR reg_path[MAX_PATH]; HKEY hk = NULL; int ret = FAIL; assert(eventlog_handle); assert(pNumRecords); assert(pLatestRecord); zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name); *eventlog_handle = NULL; *pNumRecords = 0; *pLatestRecord = 0; /* Get path to eventlog */ zbx_wsnprintf(reg_path, MAX_PATH, EVENTLOG_REG_PATH TEXT("%s"), wsource); if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_path, 0, KEY_READ, &hk)) goto out; RegCloseKey(hk); if (NULL == (*eventlog_handle = OpenEventLog(NULL, wsource))) /* open log file */ goto out; if (0 == GetNumberOfEventLogRecords(*eventlog_handle, (unsigned long*)pNumRecords)) /* get number of records */ goto out; if (0 == GetOldestEventLogRecord(*eventlog_handle, (unsigned long*)pLatestRecord)) goto out; zabbix_log(LOG_LEVEL_DEBUG, "%s() pNumRecords:%ld pLatestRecord:%ld", __function_name, *pNumRecords, *pLatestRecord); ret = SUCCEED; out: zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret)); return ret; }
/* Open event log */ static int EventlogOpen(int log) { DWORD count; DWORD oldest; /* Reset all indicators */ EventlogList[log].count = 0; EventlogList[log].pos = 0; EventlogList[log].recnum = 1; /* Open log */ EventlogList[log].handle = OpenEventLog(NULL, EventlogList[log].name); if (EventlogList[log].handle == NULL) { Log(LOG_ERROR|LOG_SYS, "Cannot open event log: \"%s\"", EventlogList[log].name); return 1; } /* Get number of records to skip */ if (GetNumberOfEventLogRecords(EventlogList[log].handle, &count) == 0) { Log(LOG_ERROR|LOG_SYS, "Cannot get record count for event log: \"%s\"", EventlogList[log].name); return 1; } /* Get oldest record number */ if (GetOldestEventLogRecord(EventlogList[log].handle, &oldest) == 0 && count != 0) { Log(LOG_ERROR|LOG_SYS, "Cannot get oldest record number for event log: \"%s\"", EventlogList[log].name); return 1; } /* Store record of next event */ EventlogList[log].recnum = oldest + count; if (EventlogList[log].recnum == 0) EventlogList[log].recnum = 1; /* ?? */ /* Success */ return 0; }
// Get the record number to the last record in the log file. static DWORD GetLastRecordNumber(HANDLE hEventLog, DWORD* pdwRecordNumber) { DWORD status = ERROR_SUCCESS; DWORD OldestRecordNumber = 0; DWORD NumberOfRecords = 0; if (!GetOldestEventLogRecord(hEventLog, &OldestRecordNumber)) { wprintf(L"GetOldestEventLogRecord failed with %lu.\n", status = GetLastError()); goto cleanup; } if (!GetNumberOfEventLogRecords(hEventLog, &NumberOfRecords)) { wprintf(L"GetOldestEventLogRecord failed with %lu.\n", status = GetLastError()); goto cleanup; } *pdwRecordNumber = OldestRecordNumber + NumberOfRecords - 1; cleanup: return status; }
static void test_readwrite(void) { HANDLE handle; PSID user; DWORD sidsize, count; BOOL ret, sidavailable; BOOL on_vista = FALSE; /* Used to indicate Vista, W2K8 or Win7 */ DWORD i; char *localcomputer = NULL; DWORD size; if (pCreateWellKnownSid) { sidsize = SECURITY_MAX_SID_SIZE; user = HeapAlloc(GetProcessHeap(), 0, sidsize); SetLastError(0xdeadbeef); pCreateWellKnownSid(WinInteractiveSid, NULL, user, &sidsize); sidavailable = TRUE; } else { win_skip("Skipping some SID related tests\n"); sidavailable = FALSE; user = NULL; } /* Write an event with an incorrect event type. This will fail on Windows 7 * but succeed on all others, hence it's not part of the struct. */ handle = OpenEventLogA(NULL, eventlogname); if (!handle) { /* Intermittently seen on NT4 when tests are run immediately after boot */ win_skip("Could not get a handle to the eventlog\n"); goto cleanup; } count = 0xdeadbeef; GetNumberOfEventLogRecords(handle, &count); if (count != 0) { /* Needed for W2K3 without a service pack */ win_skip("We most likely opened the Application eventlog\n"); CloseEventLog(handle); Sleep(2000); handle = OpenEventLogA(NULL, eventlogname); count = 0xdeadbeef; GetNumberOfEventLogRecords(handle, &count); if (count != 0) { win_skip("We didn't open our new eventlog\n"); CloseEventLog(handle); goto cleanup; } } SetLastError(0xdeadbeef); ret = ReportEventA(handle, 0x20, 0, 0, NULL, 0, 0, NULL, NULL); if (!ret && GetLastError() == ERROR_CRC) { win_skip("Win7 fails when using incorrect event types\n"); ret = ReportEventA(handle, 0, 0, 0, NULL, 0, 0, NULL, NULL); ok(ret, "Expected success : %d\n", GetLastError()); } else { void *buf; DWORD read, needed = 0; EVENTLOGRECORD *record; ok(ret, "Expected success : %d\n", GetLastError()); /* Needed to catch earlier Vista (with no ServicePack for example) */ buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); if (!(ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed)) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed); ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, needed, &read, &needed); } if (ret) { record = (EVENTLOGRECORD *)buf; /* Vista and W2K8 return EVENTLOG_SUCCESS, Windows versions before return * the written eventtype (0x20 in this case). */ if (record->EventType == EVENTLOG_SUCCESS) on_vista = TRUE; } HeapFree(GetProcessHeap(), 0, buf); } /* This will clear the eventlog. The record numbering for new * events however differs on Vista SP1+. Before Vista the first * event would be numbered 1, on Vista SP1+ it's higher as we already * had at least one event (more in case of multiple test runs without * a reboot). */ ClearEventLogA(handle, NULL); CloseEventLog(handle); /* Write a bunch of events while using different event sources */ for (i = 0; i < sizeof(read_write)/sizeof(read_write[0]); i++) { DWORD oldest; BOOL run_sidtests = read_write[i].evt_sid & sidavailable; /* We don't need to use RegisterEventSource to report events */ if (i % 2) handle = OpenEventLogA(NULL, read_write[i].evt_src); else handle = RegisterEventSourceA(NULL, read_write[i].evt_src); ok(handle != NULL, "Expected a handle\n"); SetLastError(0xdeadbeef); ret = ReportEventA(handle, read_write[i].evt_type, read_write[i].evt_cat, read_write[i].evt_id, run_sidtests ? user : NULL, read_write[i].evt_numstrings, 0, read_write[i].evt_strings, NULL); ok(ret, "Expected ReportEvent success : %d\n", GetLastError()); count = 0xdeadbeef; SetLastError(0xdeadbeef); ret = GetNumberOfEventLogRecords(handle, &count); ok(ret, "Expected GetNumberOfEventLogRecords success : %d\n", GetLastError()); todo_wine ok(count == (i + 1), "Expected %d records, got %d\n", i + 1, count); oldest = 0xdeadbeef; ret = GetOldestEventLogRecord(handle, &oldest); ok(ret, "Expected GetOldestEventLogRecord success : %d\n", GetLastError()); todo_wine ok(oldest == 1 || (oldest > 1 && oldest != 0xdeadbeef), /* Vista SP1+, W2K8 and Win7 */ "Expected oldest to be 1 or higher, got %d\n", oldest); if (oldest > 1 && oldest != 0xdeadbeef) on_vista = TRUE; SetLastError(0xdeadbeef); if (i % 2) ret = CloseEventLog(handle); else ret = DeregisterEventSource(handle); ok(ret, "Expected success : %d\n", GetLastError()); } handle = OpenEventLogA(NULL, eventlogname); count = 0xdeadbeef; ret = GetNumberOfEventLogRecords(handle, &count); ok(ret, "Expected success\n"); todo_wine ok(count == i, "Expected %d records, got %d\n", i, count); CloseEventLog(handle); if (count == 0) { skip("No events were written to the eventlog\n"); goto cleanup; } /* Report only once */ if (on_vista) skip("There is no DWORD alignment enforced for UserSid on Vista, W2K8 or Win7\n"); if (on_vista && pGetComputerNameExA) { /* New Vista+ behavior */ size = 0; SetLastError(0xdeadbeef); pGetComputerNameExA(ComputerNameDnsFullyQualified, NULL, &size); localcomputer = HeapAlloc(GetProcessHeap(), 0, size); pGetComputerNameExA(ComputerNameDnsFullyQualified, localcomputer, &size); } else { size = MAX_COMPUTERNAME_LENGTH + 1; localcomputer = HeapAlloc(GetProcessHeap(), 0, size); GetComputerNameA(localcomputer, &size); } /* Read all events from our created eventlog, one by one */ handle = OpenEventLogA(NULL, eventlogname); ok(handle != NULL, "Failed to open Event Log, got %d\n", GetLastError()); i = 0; for (;;) { void *buf; DWORD read, needed; EVENTLOGRECORD *record; char *sourcename, *computername; int k; char *ptr; BOOL run_sidtests = read_write[i].evt_sid & sidavailable; buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); SetLastError(0xdeadbeef); ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); ok(!ret, "Expected failure\n"); if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { HeapFree(GetProcessHeap(), 0, buf); ok(GetLastError() == ERROR_HANDLE_EOF, "record %d, got %d\n", i, GetLastError()); break; } buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed); ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, needed, &read, &needed); ok(ret, "Expected success: %d\n", GetLastError()); record = (EVENTLOGRECORD *)buf; ok(record->Length == read, "Expected %d, got %d\n", read, record->Length); ok(record->Reserved == 0x654c664c, "Expected 0x654c664c, got %d\n", record->Reserved); ok(record->RecordNumber == i + 1 || (on_vista && (record->RecordNumber > i + 1)), "Expected %d or higher, got %d\n", i + 1, record->RecordNumber); ok(record->EventID == read_write[i].evt_id, "Expected %d, got %d\n", read_write[i].evt_id, record->EventID); ok(record->EventType == read_write[i].evt_type, "Expected %d, got %d\n", read_write[i].evt_type, record->EventType); ok(record->NumStrings == read_write[i].evt_numstrings, "Expected %d, got %d\n", read_write[i].evt_numstrings, record->NumStrings); ok(record->EventCategory == read_write[i].evt_cat, "Expected %d, got %d\n", read_write[i].evt_cat, record->EventCategory); sourcename = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD)); ok(!lstrcmpA(sourcename, read_write[i].evt_src), "Expected '%s', got '%s'\n", read_write[i].evt_src, sourcename); computername = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1); ok(!lstrcmpiA(computername, localcomputer), "Expected '%s', got '%s'\n", localcomputer, computername); /* Before Vista, UserSid was aligned on a DWORD boundary. Next to that if * no padding was actually required a 0 DWORD was still used for padding. No * application should be relying on the padding as we are working with offsets * anyway. */ if (!on_vista) { DWORD calculated_sidoffset = sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1 + lstrlenA(computername) + 1; /* We are already DWORD aligned, there should still be some padding */ if ((((UINT_PTR)buf + calculated_sidoffset) % sizeof(DWORD)) == 0) ok(*(DWORD *)((BYTE *)buf + calculated_sidoffset) == 0, "Expected 0\n"); ok((((UINT_PTR)buf + record->UserSidOffset) % sizeof(DWORD)) == 0, "Expected DWORD alignment\n"); } if (run_sidtests) { ok(record->UserSidLength == sidsize, "Expected %d, got %d\n", sidsize, record->UserSidLength); } else { ok(record->StringOffset == record->UserSidOffset, "Expected offsets to be the same\n"); ok(record->UserSidLength == 0, "Expected 0, got %d\n", record->UserSidLength); } ok(record->DataLength == 0, "Expected 0, got %d\n", record->DataLength); ptr = (char *)((BYTE *)buf + record->StringOffset); for (k = 0; k < record->NumStrings; k++) { ok(!lstrcmpA(ptr, two_strings[k]), "Expected '%s', got '%s'\n", two_strings[k], ptr); ptr += lstrlenA(ptr) + 1; } ok(record->Length == *(DWORD *)((BYTE *)buf + record->Length - sizeof(DWORD)), "Expected the closing DWORD to contain the length of the record\n"); HeapFree(GetProcessHeap(), 0, buf); i++; } CloseEventLog(handle); /* Test clearing a real eventlog */ handle = OpenEventLogA(NULL, eventlogname); ok(handle != NULL, "Failed to open Event Log, got %d\n", GetLastError()); SetLastError(0xdeadbeef); ret = ClearEventLogA(handle, NULL); ok(ret, "Expected success\n"); count = 0xdeadbeef; ret = GetNumberOfEventLogRecords(handle, &count); ok(ret, "Expected success\n"); ok(count == 0, "Expected an empty eventlog, got %d records\n", count); CloseEventLog(handle); cleanup: HeapFree(GetProcessHeap(), 0, localcomputer); HeapFree(GetProcessHeap(), 0, user); }
BOOL QueryEventMessages(LPWSTR lpMachineName, LPWSTR lpLogName) { HWND hwndDlg = NULL; HANDLE hEventLog; EVENTLOGRECORD *pevlr; DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords = 0, dwCurrentRecord = 0, dwRecordsToRead = 0, dwFlags, dwMaxLength; size_t cchRemaining; LPWSTR lpSourceName; LPWSTR lpComputerName; LPSTR lpData; BOOL bResult = TRUE; /* Read succeeded. */ WCHAR szWindowTitle[MAX_PATH]; WCHAR szStatusText[MAX_PATH]; WCHAR szLocalDate[MAX_PATH]; WCHAR szLocalTime[MAX_PATH]; WCHAR szEventID[MAX_PATH]; WCHAR szEventTypeText[MAX_LOADSTRING]; WCHAR szCategoryID[MAX_PATH]; WCHAR szUsername[MAX_PATH]; WCHAR szEventText[EVENT_MESSAGE_FILE_BUFFER]; WCHAR szCategory[MAX_PATH]; WCHAR szData[MAX_PATH]; PWCHAR lpTitleTemplateEnd; SYSTEMTIME time; LVITEMW lviEventItem; dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ; /* Open the event log. */ hEventLog = OpenEventLogW(lpMachineName, lpLogName); if (hEventLog == NULL) { ShowLastWin32Error(); return FALSE; } lpSourceLogName = lpLogName; lpComputerName = lpMachineName; /* Disable listview redraw */ SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0); /* Clear the list view */ (void)ListView_DeleteAllItems (hwndListView); FreeRecords(); GetOldestEventLogRecord(hEventLog, &dwThisRecord); /* Get the total number of event log records. */ GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords); g_TotalRecords = dwTotalRecords; if (dwTotalRecords > 0) { EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_ENABLED); } else { EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_GRAYED); } g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(PVOID)); /* If we have at least 1000 records show the waiting dialog */ if (dwTotalRecords > 1000) { CloseHandle(CreateThread(NULL, 0, ShowStatusMessageThread, (LPVOID)&hwndDlg, 0, NULL)); } while (dwCurrentRecord < dwTotalRecords) { pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); g_RecordPtrs[dwCurrentRecord] = pevlr; bResult = ReadEventLog(hEventLog, // Event log handle dwFlags, // Sequential read 0, // Ignored for sequential read pevlr, // Pointer to buffer sizeof(EVENTLOGRECORD), // Size of buffer &dwRead, // Number of bytes read &dwNeeded); // Bytes in the next record if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER)) { HeapFree(GetProcessHeap(), 0, pevlr); pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded); g_RecordPtrs[dwCurrentRecord] = pevlr; ReadEventLogW(hEventLog, // event log handle dwFlags, // read flags 0, // offset; default is 0 pevlr, // pointer to buffer dwNeeded, // size of buffer &dwRead, // number of bytes read &dwNeeded); // bytes in next record } while (dwRead > 0) { LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, MAX_PATH); LoadStringW(hInst, IDS_NOT_AVAILABLE, szEventText, MAX_PATH); LoadStringW(hInst, IDS_NONE, szCategory, MAX_PATH); // Get the event source name. lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD)); // Get the computer name lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR)); // This ist the data section of the current event lpData = (LPSTR)((LPBYTE)pevlr + pevlr->DataOffset); // Compute the event type EventTimeToSystemTime(pevlr->TimeWritten, &time); // Get the username that generated the event GetEventUserName(pevlr, szUsername); GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, MAX_PATH); GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &time, NULL, szLocalTime, MAX_PATH); GetEventType(pevlr->EventType, szEventTypeText); GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory); StringCbPrintfW(szEventID, sizeof(szEventID), L"%u", (pevlr->EventID & 0xFFFF)); StringCbPrintfW(szCategoryID, sizeof(szCategoryID), L"%u", pevlr->EventCategory); lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM; lviEventItem.iItem = 0; lviEventItem.iSubItem = 0; lviEventItem.lParam = (LPARAM)pevlr; lviEventItem.pszText = szEventTypeText; switch (pevlr->EventType) { case EVENTLOG_ERROR_TYPE: lviEventItem.iImage = 2; break; case EVENTLOG_AUDIT_FAILURE: lviEventItem.iImage = 2; break; case EVENTLOG_WARNING_TYPE: lviEventItem.iImage = 1; break; case EVENTLOG_INFORMATION_TYPE: lviEventItem.iImage = 0; break; case EVENTLOG_AUDIT_SUCCESS: lviEventItem.iImage = 0; break; case EVENTLOG_SUCCESS: lviEventItem.iImage = 0; break; } lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem); ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate); ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime); ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName); ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory); ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID); ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername); //User ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer MultiByteToWideChar(CP_ACP, 0, lpData, pevlr->DataLength, szData, MAX_PATH); ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, szData); //Event Text dwRead -= pevlr->Length; pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length); } dwRecordsToRead--; dwCurrentRecord++; } // All events loaded if(hwndDlg) EndDialog(hwndDlg, 0); StringCchPrintfExW(szWindowTitle, sizeof(szWindowTitle) / sizeof(WCHAR), &lpTitleTemplateEnd, &cchRemaining, 0, szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */ /* lpComputerName can be NULL here if no records was read */ dwMaxLength = (DWORD)cchRemaining; if (!lpComputerName) GetComputerNameW(lpTitleTemplateEnd, &dwMaxLength); else StringCchCopyW(lpTitleTemplateEnd, dwMaxLength, lpComputerName); StringCbPrintfW(szStatusText, sizeof(szStatusText), szStatusBarTemplate, lpLogName, dwTotalRecords); // Update the status bar SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText); // Set the window title SetWindowTextW(hwndMainWindow, szWindowTitle); // Resume list view redraw SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0); // Close the event log. CloseEventLog(hEventLog); return TRUE; }
DWORD WINAPI eventLogMonitorThreadProc(LPVOID elm_info_param) { EVENTLOGRECORD *pevlr; BYTE bBuffer[BUFFER_SIZE] = { 0 }; DWORD dwRead, dwNeeded, res; DWORD reported_next_record, num_records; BOOL skip_first = FALSE; HANDLE log = NULL, event = NULL; WCHAR msgbuf[BUFFER_SIZE]; eventlogmon_info *elm_info = (eventlogmon_info *) elm_info_param; control = 0; log = OpenEventLog(NULL, L_COMPANY_NAME); if (log == NULL) { (*elm_info->cb_err)(ELM_ERR_FATAL, L"Could not open the " L_COMPANY_NAME L" event log."); goto exit_elm_thread_error; } event = CreateEvent(NULL, FALSE, FALSE, NULL); NotifyChangeEventLog(log, event); pevlr = (EVENTLOGRECORD *) &bBuffer; if (!GetNumberOfEventLogRecords(log, &num_records) || !GetOldestEventLogRecord(log, &reported_next_record)) { _snwprintf(msgbuf, BUFFER_SIZE_ELEMENTS(msgbuf), L"error %d getting eventlog info", GetLastError()); (*elm_info->cb_err)(ELM_ERR_FATAL, msgbuf); goto exit_elm_thread_error; } /* FIXME: we don't handle the situation when the eventlog was cleared, * but our pointer is less than the number of new records. for this * we'll probably have to store a timestamp, and compare against the * event record at next_record. */ if (((int)elm_info->next_record) < 0) { elm_info->next_record = reported_next_record; } else if (elm_info->next_record > (reported_next_record + num_records + 1)) { /* looks like the eventlog was cleared since we last checked * it. issue a warning and reset */ elm_info->next_record = reported_next_record; (*elm_info->cb_err)(ELM_ERR_CLEARED, L"Eventlog was cleared!\n"); } else { /* we need to ensure we SEEK to a valid record; but since * it's already been reported, don't report it again. */ elm_info->next_record--; skip_first = TRUE; } /* first seek to the last record * EVENTLOG_FORWARDS_READ indicates we will get messages in * chronological order. * FIXME: test to make sure that this works properly on * overwrite-wrapped logs */ if (!ReadEventLog(log, EVENTLOG_FORWARDS_READ | EVENTLOG_SEEK_READ, elm_info->next_record, pevlr, BUFFER_SIZE, &dwRead, &dwNeeded)) { dwRead = 0; dwNeeded = 0; } for(;;) { do { /* case 5813: if pevlr->Length is 0, we'll have an infinite * loop. this could possibly happen if drive is full? * just abort if we detect it. */ while (dwRead > 0 && pevlr->Length > 0) { if (format_messages && !skip_first) { res = get_formatted_message(pevlr, msgbuf, BUFFER_SIZE); if (res != ERROR_SUCCESS) { _snwprintf(msgbuf, BUFFER_SIZE_ELEMENTS(msgbuf), L"FormatMessage error %d\n", res); (*elm_info->cb_err)(ELM_ERR_WARN, msgbuf); } else { /* invoke the callback */ (*elm_info->cb_format)(pevlr->RecordNumber, pevlr->EventType, msgbuf, pevlr->TimeGenerated); } } else if(!skip_first) { /* xref case 3065: insurance */ if (pevlr->RecordNumber != 0 || pevlr->TimeGenerated != 0) { /* raw callback */ (*elm_info->cb_raw)(pevlr); } } else { skip_first = FALSE; } dwRead -= pevlr->Length; pevlr = (EVENTLOGRECORD *) ((LPBYTE) pevlr + pevlr->Length); } pevlr = (EVENTLOGRECORD *) &bBuffer; } while (ReadEventLog(log, EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, 0, pevlr, BUFFER_SIZE, &dwRead, &dwNeeded)); if((res = GetLastError()) != ERROR_HANDLE_EOF) { //FIXME: assert GetLastError() is appropriate _snwprintf(msgbuf, BUFFER_SIZE_ELEMENTS(msgbuf), L"Unexpected error %d reading event log\n", res); (*elm_info->cb_err)(ELM_ERR_WARN, msgbuf); } if (do_once) break; /* the event is auto-reset. timeout because NotifyChangeEventLog is not reliable. */ WaitForSingleObject(event, MINIPULSE); if(control) break; } exit_elm_thread_error: if (log != NULL) CloseEventLog(log); if (event != NULL) CloseHandle(event); free(elm_info); /* FIXME: need ExitThread()? */ return 0; }