diff --git a/base/applications/mscutils/eventvwr/eventvwr.c b/base/applications/mscutils/eventvwr/eventvwr.c index 87be9a337b3..f95a1a0643c 100644 --- a/base/applications/mscutils/eventvwr/eventvwr.c +++ b/base/applications/mscutils/eventvwr/eventvwr.c @@ -1978,7 +1978,6 @@ EnumEventsThread(IN LPVOID lpParameter) BOOL bResult = TRUE; /* Read succeeded */ HANDLE hProcessHeap = GetProcessHeap(); PSID pLastSid = NULL; - INT nItems; UINT uStep = 0, uStepAt = 0, uPos = 0; @@ -1998,7 +1997,8 @@ EnumEventsThread(IN LPVOID lpParameter) SYSTEMTIME time; LVITEMW lviEventItem; - EnableEventDetailsButtons(hwndEventDetails, FALSE); + /* Disable the Previous/Next buttons */ + SendMessageW(hwndEventDetails, EVT_DISPLAY, FALSE, (LPARAM)-1); /* Save the current event log filter globally */ EventLogFilter_AddRef(EventLogFilter); @@ -2265,9 +2265,6 @@ Quit: /* All events loaded */ Cleanup: - nItems = ListView_GetItemCount(hwndListView); - EnableEventDetailsButtons(hwndEventDetails, (nItems > 0)); - ShowWindow(hwndStatusProgress, SW_HIDE); SendMessageW(hwndListView, LVM_PROGRESS, 0, FALSE); @@ -2298,6 +2295,11 @@ Cleanup: /* Resume list view redraw */ SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0); + /* Re-enable the Previous/Next buttons, keeping the current event details + * displayed, if any. Don't auto-select the first list item but wait for + * the user to do it. */ + SendMessageW(hwndEventDetails, EVT_DISPLAY, FALSE, 0); + EventLogFilter_Release(EventLogFilter); CloseHandle(hStopEnumEvent); @@ -3342,7 +3344,7 @@ WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) MB_OK | MB_ICONERROR); break; } - SendMessageW(hwndEventDetails, EVT_DISPLAY, 0, (LPARAM)pnmv->iItem); + SendMessageW(hwndEventDetails, EVT_DISPLAY, TRUE, (LPARAM)pnmv->iItem); } break; } @@ -4347,9 +4349,9 @@ EventDetails(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) cxOld = rcWnd.right - rcWnd.left; cyOld = rcWnd.bottom - rcWnd.top; - /* Show event info in dialog control */ - iEventItem = (lParam != 0 ? ((PEVENTDETAIL_INFO)lParam)->iEventItem : 0); - SendMessageW(hWndDetailsCtrl, EVT_DISPLAY, 0, (LPARAM)iEventItem); + /* Display the event info in the dialog */ + iEventItem = (lParam != 0 ? ((PEVENTDETAIL_INFO)lParam)->iEventItem : -1); + SendMessageW(hWndDetailsCtrl, EVT_DISPLAY, TRUE, (LPARAM)iEventItem); // SetWindowPos(hWndDetailsCtrl, NULL, // 0, 0, diff --git a/base/applications/mscutils/eventvwr/evtdetctl.c b/base/applications/mscutils/eventvwr/evtdetctl.c index 1ed581a6589..89ce7df0320 100644 --- a/base/applications/mscutils/eventvwr/evtdetctl.c +++ b/base/applications/mscutils/eventvwr/evtdetctl.c @@ -4,7 +4,7 @@ * PURPOSE: Event Details Control. * COPYRIGHT: Copyright 2007 Marc Piulachs * Copyright 2008-2016 Eric Kohl - * Copyright 2016-2022 Hermès Bélusca-Maïto + * Copyright 2016-2025 Hermès Bélusca-Maïto */ #include "eventvwr.h" @@ -16,6 +16,7 @@ #define EVENT_MESSAGE_EVENTTEXT_BUFFER (1024*10) extern WCHAR szTitle[]; extern HWND hwndListView; + extern BOOL GetEventMessage(IN LPCWSTR KeyName, IN LPCWSTR SourceName, @@ -25,6 +26,9 @@ GetEventMessage(IN LPCWSTR KeyName, typedef struct _DETAILDATA { + /* The event record being displayed */ + PEVENTLOGRECORD pevlr; + /* Data initialized from EVENTDETAIL_INFO */ PEVENTLOGFILTER EventLogFilter; INT iEventItem; @@ -38,16 +42,21 @@ typedef struct _DETAILDATA } DETAILDATA, *PDETAILDATA; +static +VOID +DisplayEventData( + _In_ HWND hDlg, + _In_ PDETAILDATA pDetailData); + static VOID DisplayEvent( _In_ HWND hDlg, _In_ PDETAILDATA pDetailData) { + PEVENTLOGRECORD pevlr; PEVENTLOGFILTER EventLogFilter = pDetailData->EventLogFilter; INT iItem = pDetailData->iEventItem; - LVITEMW li; - PEVENTLOGRECORD pevlr; BOOL bEventData; WCHAR szEventType[MAX_PATH]; @@ -60,12 +69,13 @@ DisplayEvent( WCHAR szEventID[MAX_PATH]; WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER]; + /* Retrieve and cache the pointer to the selected event item */ + LVITEMW li; li.mask = LVIF_PARAM; li.iItem = iItem; li.iSubItem = 0; ListView_GetItem(hwndListView, &li); - - pevlr = (PEVENTLOGRECORD)li.lParam; + pevlr = pDetailData->pevlr = (PEVENTLOGRECORD)li.lParam; ListView_GetItemText(hwndListView, iItem, 0, szEventType, ARRAYSIZE(szEventType)); ListView_GetItemText(hwndListView, iItem, 1, szDate, ARRAYSIZE(szDate)); @@ -92,6 +102,8 @@ DisplayEvent( // FIXME: At the moment we support only one event log in the filter GetEventMessage(EventLogFilter->EventLogs[0]->LogName, szSource, pevlr, szEventText); SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText); + + DisplayEventData(hDlg, pDetailData); } static @@ -179,22 +191,17 @@ DisplayEventData( _In_ HWND hDlg, _In_ PDETAILDATA pDetailData) { + PEVENTLOGRECORD pevlr = pDetailData->pevlr; BOOL bDisplayWords = pDetailData->bDisplayWords; - INT iItem = pDetailData->iEventItem; - LVITEMW li; - PEVENTLOGRECORD pevlr; LPBYTE pData; UINT i, uOffset; UINT uBufferSize, uLineLength; PWCHAR pTextBuffer, pLine; - li.mask = LVIF_PARAM; - li.iItem = iItem; - li.iSubItem = 0; - ListView_GetItem(hwndListView, &li); + if (!pevlr) + return; - pevlr = (PEVENTLOGRECORD)li.lParam; if (pevlr->DataLength == 0) { SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L""); @@ -728,6 +735,46 @@ OnSize(HWND hDlg, PDETAILDATA pData, INT cx, INT cy) } } +static +VOID +EnableNavigationArrows( + _In_ HWND hDlg, + _In_ BOOL bEnable) +{ + /* Enable Previous/Next only if there is more than one item in the list */ + if (bEnable) + bEnable &= (ListView_GetItemCount(hwndListView) > 1); + EnableDlgItem(hDlg, IDC_PREVIOUS, bEnable); + EnableDlgItem(hDlg, IDC_NEXT, bEnable); +} + +static +VOID +ClearContents( + _In_ HWND hDlg) +{ + /* Disable the Previous/Next and Copy buttons */ + EnableNavigationArrows(hDlg, FALSE); + EnableDlgItem(hDlg, IDC_COPY, FALSE); + + /* Disable the Bytes/Words mode buttons */ + EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE); + EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE); + + /* Clear the data fields */ + SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, L""); + SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, L""); + + SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, L""); + SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L""); +} + static VOID InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData) @@ -761,6 +808,20 @@ InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData) SendDlgItemMessageW(hDlg, pData->bDisplayWords ? IDC_WORDRADIO : IDC_BYTESRADIO, BM_SETCHECK, BST_CHECKED, 0); SendDlgItemMessageW(hDlg, IDC_EVENTDATAEDIT, WM_SETFONT, (WPARAM)pData->hMonospaceFont, (LPARAM)TRUE); + + //ClearContents(hDlg); + if (pData->iEventItem != -1) + { + EnableNavigationArrows(hDlg, TRUE); + EnableDlgItem(hDlg, IDC_COPY, TRUE); + } + else + { + EnableNavigationArrows(hDlg, FALSE); + EnableDlgItem(hDlg, IDC_COPY, FALSE); + } + EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE); + EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE); } /* Message handler for Event Details control */ @@ -806,9 +867,8 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) pData->scPos.x = pData->scPos.y = 0; InitDetailsDlgCtrl(hDlg, pData); - - EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), FALSE); - EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), FALSE); + /* NOTE: Showing the event (if any) is currently delayed to later */ + // SendMessageW(hDlg, EVT_DISPLAY, TRUE, (LPARAM)pData->iEventItem); // OnSize(hDlg, pData, pData->cxOld, pData->cyOld); return (INT_PTR)TRUE; @@ -824,17 +884,58 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) return (INT_PTR)TRUE; case EVT_SETFILTER: + { + /* Disable the display first, before changing the current filter */ + pData->pevlr = NULL; + pData->iEventItem = -1; + ClearContents(hDlg); pData->EventLogFilter = (PEVENTLOGFILTER)lParam; return (INT_PTR)TRUE; + } case EVT_DISPLAY: { - pData->iEventItem = (INT)lParam; - if (pData->EventLogFilter) + if (wParam) { - /* Show event info in control */ - DisplayEvent(hDlg, pData); - DisplayEventData(hDlg, pData); + INT iEventItem = (INT)lParam; + + /* If no filter is set, don't change anything */ + if (!pData->EventLogFilter) + return (INT_PTR)TRUE; + + /* If we re-enable display from previously disabled state, re-enable the buttons */ + if ((pData->iEventItem == -1) && (iEventItem != -1)) + { + EnableNavigationArrows(hDlg, TRUE); + EnableDlgItem(hDlg, IDC_COPY, TRUE); + } + else + /* If we disable display from previously enabled state, clear and disable it */ + if ((pData->iEventItem != -1) && (iEventItem == -1)) + { + ClearContents(hDlg); + } + + /* Set the new item */ + pData->pevlr = NULL; + pData->iEventItem = iEventItem; + + /* Display the event info, if there is one */ + if (pData->iEventItem != -1) + DisplayEvent(hDlg, pData); + } + else + { + /* Enable or disable the Previous/Next buttons, + * but keep the existing contents, if any */ + EnableNavigationArrows(hDlg, (lParam != -1)); + + // HACK: Disable the Bytes/Words mode buttons + // because we won't have access anymore to the + // event data. (This will be fixed in the future.) + pData->pevlr = NULL; // Invalidate also the cache. + EnableDlgItem(hDlg, IDC_BYTESRADIO, FALSE); + EnableDlgItem(hDlg, IDC_WORDRADIO, FALSE); } return (INT_PTR)TRUE; } @@ -846,25 +947,33 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) case IDC_NEXT: { BOOL bPrev = (LOWORD(wParam) == IDC_PREVIOUS); - INT iItem, iSel, nItems = ListView_GetItemCount(hwndListView); - WCHAR szText[200]; + INT nItems = ListView_GetItemCount(hwndListView); + INT iItem, iSel; if (nItems <= 0) /* No items? */ break; + /* Get the index of the first selected item */ + iSel = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED); + /* Select the previous/next item from our current one */ - iItem = ListView_GetNextItem(hwndListView, -1, LVNI_ALL | LVNI_SELECTED); - iItem = ListView_GetNextItem(hwndListView, iItem, + iItem = ListView_GetNextItem(hwndListView, iSel, (bPrev ? LVNI_ABOVE : LVNI_BELOW)); if (iItem < 0 || iItem >= nItems) { - LoadStringW(hInst, - (bPrev ? IDS_CONTFROMEND : IDS_CONTFROMBEGINNING), - szText, _countof(szText)); - if (MessageBoxW(hDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) == IDNO) - break; + /* Confirm selection restart only if an item was previously + * selected. If not, just proceed with default selection. */ + if (iSel != -1) + { + WCHAR szText[200]; + LoadStringW(hInst, + (bPrev ? IDS_CONTFROMEND : IDS_CONTFROMBEGINNING), + szText, _countof(szText)); + if (MessageBoxW(hDlg, szText, szTitle, MB_YESNO | MB_ICONQUESTION) != IDYES) + break; + } - /* Determine from where to restart */ + /* Determine where to restart from */ iItem = (bPrev ? (nItems - 1) : 0); } @@ -886,14 +995,12 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) LVIS_FOCUSED | LVIS_SELECTED); ListView_EnsureVisible(hwndListView, iItem, FALSE); + pData->pevlr = NULL; pData->iEventItem = iItem; - /* Show event info in control */ + /* Display the event info */ if (pData->EventLogFilter) - { DisplayEvent(hDlg, pData); - DisplayEventData(hDlg, pData); - } return (INT_PTR)TRUE; } @@ -904,14 +1011,10 @@ EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) case IDC_BYTESRADIO: case IDC_WORDRADIO: - { + pData->bDisplayWords = (LOWORD(wParam) == IDC_WORDRADIO); if (pData->EventLogFilter) - { - pData->bDisplayWords = (LOWORD(wParam) == IDC_WORDRADIO); DisplayEventData(hDlg, pData); - } return (INT_PTR)TRUE; - } default: break; @@ -962,11 +1065,3 @@ CreateEventDetailsCtrl(HINSTANCE hInstance, MAKEINTRESOURCEW(IDD_EVENTDETAILS_CTRL), hParentWnd, EventDetailsCtrl, lParam); } - -VOID -EnableEventDetailsButtons(HWND hWnd, BOOL bEnable) -{ - EnableDlgItem(hWnd, IDC_PREVIOUS, bEnable); - EnableDlgItem(hWnd, IDC_NEXT, bEnable); - EnableDlgItem(hWnd, IDC_COPY, bEnable); -} diff --git a/base/applications/mscutils/eventvwr/evtdetctl.h b/base/applications/mscutils/eventvwr/evtdetctl.h index cb22cfa0d0a..eea74161417 100644 --- a/base/applications/mscutils/eventvwr/evtdetctl.h +++ b/base/applications/mscutils/eventvwr/evtdetctl.h @@ -4,7 +4,7 @@ * PURPOSE: Event Details Control. * COPYRIGHT: Copyright 2007 Marc Piulachs * Copyright 2008-2016 Eric Kohl - * Copyright 2016-2022 Hermès Bélusca-Maïto + * Copyright 2016-2025 Hermès Bélusca-Maïto */ #pragma once @@ -24,5 +24,3 @@ HWND CreateEventDetailsCtrl(HINSTANCE hInstance, HWND hParentWnd, LPARAM lParam); - -VOID EnableEventDetailsButtons(HWND hWnd, BOOL bEnable);