reactos/base/applications/mscutils/eventvwr/evtdetctl.c
Hermès Bélusca-Maïto bf3589a280
[EVENTVWR] Additions for the Event Viewer.
CORE-11637, CORE-12269

- Implement support for remote connections to NT computers to view their
  event logs (and the event logs settings). For the moment the remote
  computer name specification is is only available via the command-line.
  Note that the paths to the event log files need also to be translated
  to network-share format.
- Implement loading and saving the settings of the event viewer.
- Implement showing/hiding the events description pane, the ListView
  grid, and whether or not to save the EventViewer settings.
- Handle hypertext link click handling for the RichEdit edit box of the
  events description dialog.
2018-04-17 23:17:48 +02:00

945 lines
28 KiB
C

/*
* PROJECT: ReactOS Event Log Viewer
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/mscutils/eventvwr/evtdetctl.c
* PURPOSE: Event Details Control
* PROGRAMMERS: Marc Piulachs (marc.piulachs at codexchange [dot] net)
* Eric Kohl
* Hermes Belusca-Maito
*/
#include "eventvwr.h"
#include "evtdetctl.h"
#include <shellapi.h>
// FIXME:
#define EVENT_MESSAGE_EVENTTEXT_BUFFER 1024*10
extern HWND hwndListView;
extern BOOL
GetEventMessage(IN LPCWSTR KeyName,
IN LPCWSTR SourceName,
IN PEVENTLOGRECORD pevlr,
OUT PWCHAR EventText);
typedef struct _DETAILDATA
{
PEVENTLOGFILTER EventLogFilter;
BOOL bDisplayWords;
HFONT hMonospaceFont;
INT cxMin, cyMin;
INT cxOld, cyOld;
POINT scPos;
} DETAILDATA, *PDETAILDATA;
static
VOID
DisplayEvent(HWND hDlg, PEVENTLOGFILTER EventLogFilter)
{
WCHAR szEventType[MAX_PATH];
WCHAR szTime[MAX_PATH];
WCHAR szDate[MAX_PATH];
WCHAR szUser[MAX_PATH];
WCHAR szComputer[MAX_PATH];
WCHAR szSource[MAX_PATH];
WCHAR szCategory[MAX_PATH];
WCHAR szEventID[MAX_PATH];
WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
BOOL bEventData = FALSE;
LVITEMW li;
PEVENTLOGRECORD pevlr;
int iIndex;
/* Get index of selected item */
iIndex = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED | LVNI_FOCUSED);
if (iIndex == -1)
{
MessageBoxW(hDlg,
L"No Items in ListView",
L"Error",
MB_OK | MB_ICONINFORMATION);
return;
}
li.mask = LVIF_PARAM;
li.iItem = iIndex;
li.iSubItem = 0;
ListView_GetItem(hwndListView, &li);
pevlr = (PEVENTLOGRECORD)li.lParam;
ListView_GetItemText(hwndListView, iIndex, 0, szEventType, ARRAYSIZE(szEventType));
ListView_GetItemText(hwndListView, iIndex, 1, szDate, ARRAYSIZE(szDate));
ListView_GetItemText(hwndListView, iIndex, 2, szTime, ARRAYSIZE(szTime));
ListView_GetItemText(hwndListView, iIndex, 3, szSource, ARRAYSIZE(szSource));
ListView_GetItemText(hwndListView, iIndex, 4, szCategory, ARRAYSIZE(szCategory));
ListView_GetItemText(hwndListView, iIndex, 5, szEventID, ARRAYSIZE(szEventID));
ListView_GetItemText(hwndListView, iIndex, 6, szUser, ARRAYSIZE(szUser));
ListView_GetItemText(hwndListView, iIndex, 7, szComputer, ARRAYSIZE(szComputer));
SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
bEventData = (pevlr->DataLength > 0);
EnableDlgItem(hDlg, IDC_BYTESRADIO, bEventData);
EnableDlgItem(hDlg, IDC_WORDRADIO, bEventData);
// 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);
}
static
UINT
PrintByteDataLine(PWCHAR pBuffer, UINT uOffset, PBYTE pData, UINT uLength)
{
PWCHAR p = pBuffer;
UINT n, i, r = 0;
if (uOffset != 0)
{
n = swprintf(p, L"\r\n");
p += n;
r += n;
}
n = swprintf(p, L"%04lx:", uOffset);
p += n;
r += n;
for (i = 0; i < uLength; i++)
{
n = swprintf(p, L" %02x", pData[i]);
p += n;
r += n;
}
for (i = 0; i < 9 - uLength; i++)
{
n = swprintf(p, L" ");
p += n;
r += n;
}
for (i = 0; i < uLength; i++)
{
// NOTE: Normally iswprint should return FALSE for tabs...
n = swprintf(p, L"%c", (iswprint(pData[i]) && (pData[i] != L'\t')) ? pData[i] : L'.');
p += n;
r += n;
}
return r;
}
static
UINT
PrintWordDataLine(PWCHAR pBuffer, UINT uOffset, PULONG pData, UINT uLength)
{
PWCHAR p = pBuffer;
UINT n, i, r = 0;
if (uOffset != 0)
{
n = swprintf(p, L"\r\n");
p += n;
r += n;
}
n = swprintf(p, L"%04lx:", uOffset);
p += n;
r += n;
for (i = 0; i < uLength / sizeof(ULONG); i++)
{
n = swprintf(p, L" %08lx", pData[i]);
p += n;
r += n;
}
/* Display the remaining bytes if uLength was not a multiple of sizeof(ULONG) */
for (i = (uLength / sizeof(ULONG)) * sizeof(ULONG); i < uLength; i++)
{
n = swprintf(p, L" %02x", ((PBYTE)pData)[i]);
p += n;
r += n;
}
return r;
}
static
VOID
DisplayEventData(HWND hDlg, BOOL bDisplayWords)
{
LVITEMW li;
PEVENTLOGRECORD pevlr;
int iIndex;
LPBYTE pData;
UINT i, uOffset;
UINT uBufferSize, uLineLength;
PWCHAR pTextBuffer, pLine;
/* Get index of selected item */
iIndex = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED | LVNI_FOCUSED);
if (iIndex == -1)
{
MessageBoxW(hDlg,
L"No Items in ListView",
L"Error",
MB_OK | MB_ICONINFORMATION);
return;
}
li.mask = LVIF_PARAM;
li.iItem = iIndex;
li.iSubItem = 0;
ListView_GetItem(hwndListView, &li);
pevlr = (PEVENTLOGRECORD)li.lParam;
if (pevlr->DataLength == 0)
{
SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L"");
return;
}
if (bDisplayWords)
uBufferSize = ((pevlr->DataLength / 8) + 1) * 26 * sizeof(WCHAR);
else
uBufferSize = ((pevlr->DataLength / 8) + 1) * 43 * sizeof(WCHAR);
pTextBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uBufferSize);
if (!pTextBuffer)
return;
pLine = pTextBuffer;
uOffset = 0;
for (i = 0; i < pevlr->DataLength / 8; i++)
{
pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset);
if (bDisplayWords)
uLineLength = PrintWordDataLine(pLine, uOffset, (PULONG)pData, 8);
else
uLineLength = PrintByteDataLine(pLine, uOffset, pData, 8);
pLine = pLine + uLineLength;
uOffset += 8;
}
if (pevlr->DataLength % 8 != 0)
{
pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset);
if (bDisplayWords)
PrintWordDataLine(pLine, uOffset, (PULONG)pData, pevlr->DataLength % 8);
else
PrintByteDataLine(pLine, uOffset, pData, pevlr->DataLength % 8);
}
SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, pTextBuffer);
HeapFree(GetProcessHeap(), 0, pTextBuffer);
}
static
HFONT
CreateMonospaceFont(VOID)
{
LOGFONTW tmpFont = {0};
HFONT hFont;
HDC hDC;
hDC = GetDC(NULL);
tmpFont.lfHeight = -MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72);
tmpFont.lfWeight = FW_NORMAL;
wcscpy(tmpFont.lfFaceName, L"Courier New");
hFont = CreateFontIndirectW(&tmpFont);
ReleaseDC(NULL, hDC);
return hFont;
}
static
VOID
CopyEventEntry(HWND hWnd)
{
WCHAR tmpHeader[512];
WCHAR szEventType[MAX_PATH];
WCHAR szSource[MAX_PATH];
WCHAR szCategory[MAX_PATH];
WCHAR szEventID[MAX_PATH];
WCHAR szDate[MAX_PATH];
WCHAR szTime[MAX_PATH];
WCHAR szUser[MAX_PATH];
WCHAR szComputer[MAX_PATH];
WCHAR evtDesc[EVENT_MESSAGE_EVENTTEXT_BUFFER];
ULONG size = 0;
LPWSTR output;
HGLOBAL hMem;
/* Try to open the clipboard */
if (!OpenClipboard(hWnd))
return;
/* Get the formatted text needed to place the content into */
size += LoadStringW(hInst, IDS_COPY, tmpHeader, ARRAYSIZE(tmpHeader));
/* Grab all the information and get it ready for the clipboard */
size += GetDlgItemTextW(hWnd, IDC_EVENTTYPESTATIC, szEventType, ARRAYSIZE(szEventType));
size += GetDlgItemTextW(hWnd, IDC_EVENTSOURCESTATIC, szSource, ARRAYSIZE(szSource));
size += GetDlgItemTextW(hWnd, IDC_EVENTCATEGORYSTATIC, szCategory, ARRAYSIZE(szCategory));
size += GetDlgItemTextW(hWnd, IDC_EVENTIDSTATIC, szEventID, ARRAYSIZE(szEventID));
size += GetDlgItemTextW(hWnd, IDC_EVENTDATESTATIC, szDate, ARRAYSIZE(szDate));
size += GetDlgItemTextW(hWnd, IDC_EVENTTIMESTATIC, szTime, ARRAYSIZE(szTime));
size += GetDlgItemTextW(hWnd, IDC_EVENTUSERSTATIC, szUser, ARRAYSIZE(szUser));
size += GetDlgItemTextW(hWnd, IDC_EVENTCOMPUTERSTATIC, szComputer, ARRAYSIZE(szComputer));
size += GetDlgItemTextW(hWnd, IDC_EVENTTEXTEDIT, evtDesc, ARRAYSIZE(evtDesc));
size++; /* Null-termination */
size *= sizeof(WCHAR);
/*
* Consolidate the information into one big piece and
* sort out the memory needed to write to the clipboard.
*/
hMem = GlobalAlloc(GMEM_MOVEABLE, size);
if (hMem == NULL) goto Quit;
output = GlobalLock(hMem);
if (output == NULL)
{
GlobalFree(hMem);
goto Quit;
}
StringCbPrintfW(output, size,
tmpHeader, szEventType, szSource, szCategory, szEventID,
szDate, szTime, szUser, szComputer, evtDesc);
GlobalUnlock(hMem);
/* We succeeded, empty the clipboard and write the data in it */
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, hMem);
Quit:
/* Close the clipboard once we are done with it */
CloseClipboard();
}
static
VOID
OnLink(HWND hDlg, ENLINK* penLink)
{
LPWSTR pLink;
TEXTRANGE txtRange;
ASSERT(penLink->nmhdr.idFrom == IDC_EVENTTEXTEDIT);
/* Only act on left button up events */
if (penLink->msg != WM_LBUTTONUP)
return;
/* If the range is empty, do nothing */
if (penLink->chrg.cpMin == penLink->chrg.cpMax)
return;
/* Allocate memory for the text link */
pLink = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
(max(penLink->chrg.cpMin, penLink->chrg.cpMax) -
min(penLink->chrg.cpMin, penLink->chrg.cpMax) + 1) * sizeof(WCHAR));
if (!pLink)
{
/* Not enough memory, bail out */
return;
}
txtRange.chrg = penLink->chrg;
txtRange.lpstrText = pLink;
SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_GETTEXTRANGE, 0, (LPARAM)&txtRange);
/* Open the link */
ShellExecuteW(hDlg, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
/* Free the buffer */
HeapFree(GetProcessHeap(), 0, pLink);
}
static
VOID
OnScroll(HWND hDlg, PDETAILDATA pData, INT nBar, WORD sbCode)
{
RECT rect;
SCROLLINFO sInfo;
INT oldPos, Maximum;
PLONG pOriginXY;
ASSERT(nBar == SB_HORZ || nBar == SB_VERT);
GetClientRect(hDlg, &rect);
if (nBar == SB_HORZ)
{
Maximum = pData->cxMin - (rect.right-rect.left) /* pData->cxOld */;
pOriginXY = &pData->scPos.x;
}
else // if (nBar == SB_VERT)
{
Maximum = pData->cyMin - (rect.bottom-rect.top) /* pData->cyOld */;
pOriginXY = &pData->scPos.y;
}
/* Set scrollbar sizes */
sInfo.cbSize = sizeof(sInfo);
sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
if (!GetScrollInfo(hDlg, nBar, &sInfo))
return;
oldPos = sInfo.nPos;
switch (sbCode)
{
case SB_LINEUP: // SB_LINELEFT:
sInfo.nPos--;
break;
case SB_LINEDOWN: // SB_LINERIGHT:
sInfo.nPos++;
break;
case SB_PAGEUP: // SB_PAGELEFT:
sInfo.nPos -= sInfo.nPage;
break;
case SB_PAGEDOWN: // SB_PAGERIGHT:
sInfo.nPos += sInfo.nPage;
break;
case SB_THUMBTRACK:
sInfo.nPos = sInfo.nTrackPos;
break;
case SB_THUMBPOSITION:
sInfo.nPos = sInfo.nTrackPos;
break;
case SB_TOP: // SB_LEFT:
sInfo.nPos = sInfo.nMin;
break;
case SB_BOTTOM: // SB_RIGHT:
sInfo.nPos = sInfo.nMax;
break;
default:
break;
}
sInfo.nPos = min(max(sInfo.nPos, 0), Maximum);
if (oldPos != sInfo.nPos)
{
POINT scOldPos = pData->scPos;
/* We now modify pData->scPos */
*pOriginXY = sInfo.nPos;
ScrollWindowEx(hDlg,
(scOldPos.x - pData->scPos.x),
(scOldPos.y - pData->scPos.y),
NULL,
NULL,
NULL,
NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN);
sInfo.fMask = SIF_POS;
SetScrollInfo(hDlg, nBar, &sInfo, TRUE);
// UpdateWindow(hDlg);
}
}
static VOID
OnSize(HWND hDlg, PDETAILDATA pData, INT cx, INT cy)
{
LONG_PTR dwStyle;
INT sbVXSize, sbHYSize;
SCROLLINFO sInfo;
POINT scOldPos;
HDWP hdwp;
HWND hItemWnd;
RECT rect;
INT y = 0;
if (!pData)
return;
dwStyle = GetWindowLongPtrW(hDlg, GWL_STYLE);
sbVXSize = GetSystemMetrics(SM_CXVSCROLL);
sbHYSize = GetSystemMetrics(SM_CYHSCROLL);
/* Compensate for existing scroll bars (because lParam values do not accommodate scroll bar) */
if (dwStyle & WS_HSCROLL) cy += sbHYSize; // Window currently has a horizontal scrollbar
if (dwStyle & WS_VSCROLL) cx += sbVXSize; // Window currently has a vertical scrollbar
/* Compensate for added scroll bars in window */
if (cx < pData->cxMin) cy -= sbHYSize; // Window will have a horizontal scroll bar
if (cy < pData->cyMin) cx -= sbVXSize; // Window will have a vertical scroll bar
/* Set scrollbar sizes */
sInfo.cbSize = sizeof(sInfo);
sInfo.fMask = SIF_POS;
if (GetScrollInfo(hDlg, SB_VERT, &sInfo))
scOldPos.y = sInfo.nPos;
else
scOldPos.y = pData->scPos.y;
sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
sInfo.nMin = 0;
if (pData->cyMin > cy)
{
sInfo.nMax = pData->cyMin - 1;
sInfo.nPage = cy;
sInfo.nPos = pData->scPos.y;
SetScrollInfo(hDlg, SB_VERT, &sInfo, TRUE);
/* Display the scrollbar if needed */
if (!(dwStyle & WS_VSCROLL))
ShowScrollBar(hDlg, SB_VERT, TRUE);
}
else
{
scOldPos.y = 0;
sInfo.nMax = pData->cyMin - 1;
sInfo.nPage = cy;
sInfo.nPos = pData->scPos.y;
sInfo.nPos = scOldPos.y;
SetScrollInfo(hDlg, SB_VERT, &sInfo, TRUE);
ShowScrollBar(hDlg, SB_VERT, FALSE);
rect.left = cx - sbVXSize;
rect.right = cx;
rect.top = 0;
rect.bottom = cy;
InvalidateRect(hDlg, &rect, TRUE);
}
sInfo.fMask = SIF_POS;
if (GetScrollInfo(hDlg, SB_HORZ, &sInfo))
scOldPos.x = sInfo.nPos;
else
scOldPos.x = pData->scPos.x;
sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
sInfo.nMin = 0;
if (pData->cxMin > cx)
{
sInfo.nMax = pData->cxMin - 1;
sInfo.nPage = cx;
sInfo.nPos = pData->scPos.x;
SetScrollInfo(hDlg, SB_HORZ, &sInfo, TRUE);
/* Display the scrollbar if needed */
if (!(dwStyle & WS_HSCROLL))
ShowScrollBar(hDlg, SB_HORZ, TRUE);
}
else
{
scOldPos.x = 0;
sInfo.nMax = pData->cxMin - 1;
sInfo.nPage = cx;
sInfo.nPos = pData->scPos.x;
sInfo.nPos = scOldPos.x;
SetScrollInfo(hDlg, SB_HORZ, &sInfo, TRUE);
ShowScrollBar(hDlg, SB_HORZ, FALSE);
rect.left = 0;
rect.right = cx;
rect.top = cy - sbHYSize;
rect.bottom = cy;
InvalidateRect(hDlg, &rect, TRUE);
}
if ((scOldPos.x != pData->scPos.x) || (scOldPos.y != pData->scPos.y))
{
ScrollWindowEx(hDlg,
// (scOldPos.x - pData->scPos.x),
(pData->scPos.x - scOldPos.x),
// (scOldPos.y - pData->scPos.y),
(pData->scPos.y - scOldPos.y),
NULL,
NULL,
NULL,
NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN);
pData->scPos = scOldPos;
}
// /* Adjust the start of the visible area if we are attempting to show nonexistent areas */
// if ((pData->cxMin - pData->scPos.x) < cx) pData->scPos.x = pData->cxMin - cx;
// if ((pData->cyMin - pData->scPos.y) < cy) pData->scPos.y = pData->cyMin - cy;
// // InvalidateRect(GuiData->hWindow, NULL, TRUE);
/* Forbid resizing the control smaller than its minimal size */
if (cx < pData->cxMin) cx = pData->cxMin;
if (cy < pData->cyMin) cy = pData->cyMin;
if ((cx != pData->cxOld) || (cy != pData->cyOld))
{
hdwp = BeginDeferWindowPos(8);
/* Move the edit boxes */
GetWindowRect(hDlg, &rect);
hItemWnd = GetDlgItem(hDlg, IDC_EVENTTEXTEDIT);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
// OffsetRect(&rect, 0, y);
// y += (cy - pData->cyOld) / 2 ; // + (cy - pData->cyOld) % 2;
/** y += (cy - pData->cyOld) / 2 ; // + (cy - pData->cyOld) % 2; **/
if (cy >= pData->cyOld)
y += (cy - pData->cyOld) / 2 + (cy - pData->cyOld) % 2;
else
y -= (pData->cyOld - cy) / 2 + (pData->cyOld - cy) % 2;
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left, rect.top,
(rect.right - rect.left) + (cx - pData->cxOld),
(rect.bottom - rect.top) + y,
/** SWP_NOMOVE | **/ SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_DETAILS_STATIC);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
// OffsetRect(&rect, 0, y);
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left, rect.top + y,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_BYTESRADIO);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
// OffsetRect(&rect, 0, y);
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left, rect.top + y,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_WORDRADIO);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
// OffsetRect(&rect, 0, y);
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left, rect.top + y,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_EVENTDATAEDIT);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
// OffsetRect(&rect, 0, y);
// // y -= (cy - pData->cyOld) % 2;
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left, rect.top + y,
(rect.right - rect.left) + (cx - pData->cxOld),
(rect.bottom - rect.top) + y,
SWP_NOZORDER | SWP_NOACTIVATE);
/* Move the buttons */
hItemWnd = GetDlgItem(hDlg, IDC_PREVIOUS);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left + (cx - pData->cxOld),
rect.top,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_NEXT);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left + (cx - pData->cxOld),
rect.top,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
hItemWnd = GetDlgItem(hDlg, IDC_COPY);
GetWindowRect(hItemWnd, &rect);
MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT));
if (hdwp)
hdwp = DeferWindowPos(hdwp,
hItemWnd,
0,
rect.left + (cx - pData->cxOld),
rect.top,
0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
if (hdwp)
EndDeferWindowPos(hdwp);
pData->cxOld = cx;
pData->cyOld = cy;
}
}
static
VOID
InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData)
{
DWORD dwMask;
HANDLE nextIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_NEXT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
HANDLE prevIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_PREV), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
HANDLE copyIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_COPY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
SendDlgItemMessageW(hDlg, IDC_NEXT, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)nextIcon);
SendDlgItemMessageW(hDlg, IDC_PREVIOUS, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)prevIcon);
SendDlgItemMessageW(hDlg, IDC_COPY, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)copyIcon);
/* Set the default read-only RichEdit color */
SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_3DFACE));
/* Enable RichEdit coloured and underlined links */
dwMask = SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_GETEVENTMASK, 0, 0);
SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_SETEVENTMASK, 0, dwMask | ENM_LINK | ENM_MOUSEEVENTS);
/*
* Activate automatic URL recognition by the RichEdit control. For more information, see:
* https://blogs.msdn.microsoft.com/murrays/2009/08/31/automatic-richedit-hyperlinks/
* https://blogs.msdn.microsoft.com/murrays/2009/09/24/richedit-friendly-name-hyperlinks/
* https://msdn.microsoft.com/en-us/library/windows/desktop/bb787991(v=vs.85).aspx
*/
SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_AUTOURLDETECT, AURL_ENABLEURL /* | AURL_ENABLEEAURLS */, 0);
/* Note that the RichEdit control never gets themed under WinXP+; one would have to write code to simulate Edit-control theming */
SendDlgItemMessageW(hDlg, pData->bDisplayWords ? IDC_WORDRADIO : IDC_BYTESRADIO, BM_SETCHECK, BST_CHECKED, 0);
SendDlgItemMessageW(hDlg, IDC_EVENTDATAEDIT, WM_SETFONT, (WPARAM)pData->hMonospaceFont, (LPARAM)TRUE);
}
/* Message handler for Event Details control */
static
INT_PTR CALLBACK
EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
PDETAILDATA pData;
pData = (PDETAILDATA)GetWindowLongPtrW(hDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
{
RECT rect;
pData = (PDETAILDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pData));
if (!pData)
{
EndDialog(hDlg, 0);
return (INT_PTR)TRUE;
}
SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)pData);
pData->EventLogFilter = (PEVENTLOGFILTER)lParam;
pData->bDisplayWords = FALSE;
pData->hMonospaceFont = CreateMonospaceFont();
GetClientRect(hDlg, &rect);
pData->cxOld = pData->cxMin = rect.right - rect.left;
pData->cyOld = pData->cyMin = rect.bottom - rect.top;
pData->scPos.x = pData->scPos.y = 0;
InitDetailsDlgCtrl(hDlg, pData);
#if 0
/* Show event info on dialog box */
DisplayEvent(hDlg, pData->EventLogFilter);
DisplayEventData(hDlg, pData->bDisplayWords);
#endif
// OnSize(hDlg, pData, pData->cxOld, pData->cyOld);
return (INT_PTR)TRUE;
}
case WM_DESTROY:
if (pData)
{
if (pData->hMonospaceFont)
DeleteObject(pData->hMonospaceFont);
HeapFree(GetProcessHeap(), 0, pData);
}
return (INT_PTR)TRUE;
case EVT_SETFILTER:
pData->EventLogFilter = (PEVENTLOGFILTER)lParam;
return (INT_PTR)TRUE;
case EVT_DISPLAY:
if (pData->EventLogFilter)
{
/* Show event info on dialog box */
DisplayEvent(hDlg, pData->EventLogFilter);
DisplayEventData(hDlg, pData->bDisplayWords);
}
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_PREVIOUS:
{
SendMessageW(hwndListView, WM_KEYDOWN, VK_UP, 0);
/* Show event info on dialog box */
if (pData->EventLogFilter)
{
DisplayEvent(hDlg, pData->EventLogFilter);
DisplayEventData(hDlg, pData->bDisplayWords);
}
return (INT_PTR)TRUE;
}
case IDC_NEXT:
{
SendMessageW(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
/* Show event info on dialog box */
if (pData->EventLogFilter)
{
DisplayEvent(hDlg, pData->EventLogFilter);
DisplayEventData(hDlg, pData->bDisplayWords);
}
return (INT_PTR)TRUE;
}
case IDC_COPY:
if (pData->EventLogFilter)
CopyEventEntry(hDlg);
return (INT_PTR)TRUE;
case IDC_BYTESRADIO:
if (pData->EventLogFilter)
{
pData->bDisplayWords = FALSE;
DisplayEventData(hDlg, pData->bDisplayWords);
}
return (INT_PTR)TRUE;
case IDC_WORDRADIO:
if (pData->EventLogFilter)
{
pData->bDisplayWords = TRUE;
DisplayEventData(hDlg, pData->bDisplayWords);
}
return (INT_PTR)TRUE;
default:
break;
}
break;
case WM_NOTIFY:
{
LPNMHDR hdr = (LPNMHDR)lParam;
if (hdr->idFrom == IDC_EVENTTEXTEDIT)
{
switch (hdr->code)
{
case EN_LINK:
OnLink(hDlg, (ENLINK*)lParam);
break;
}
}
break;
}
case WM_HSCROLL:
OnScroll(hDlg, pData, SB_HORZ, LOWORD(wParam));
SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0);
return (INT_PTR)TRUE;
case WM_VSCROLL:
OnScroll(hDlg, pData, SB_VERT, LOWORD(wParam));
SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0);
return (INT_PTR)TRUE;
case WM_SIZE:
OnSize(hDlg, pData, LOWORD(lParam), HIWORD(lParam));
SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0);
return (INT_PTR)TRUE;
}
return (INT_PTR)FALSE;
}
HWND
CreateEventDetailsCtrl(HINSTANCE hInstance,
HWND hParentWnd,
LPARAM lParam)
{
return CreateDialogParamW(hInstance,
MAKEINTRESOURCEW(IDD_EVENTDETAILS_CTRL),
hParentWnd, EventDetailsCtrl, lParam);
}