1 /* 2 * PROJECT: ReactOS Event Log Viewer 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/mscutils/eventvwr/evtdetctl.c 5 * PURPOSE: Event Details Control 6 * PROGRAMMERS: Marc Piulachs (marc.piulachs at codexchange [dot] net) 7 * Eric Kohl 8 * Hermes Belusca-Maito 9 */ 10 11 #include "eventvwr.h" 12 #include "evtdetctl.h" 13 14 // FIXME: 15 #define EVENT_MESSAGE_EVENTTEXT_BUFFER 1024*10 16 extern HWND hwndListView; 17 extern BOOL 18 GetEventMessage(IN LPCWSTR KeyName, 19 IN LPCWSTR SourceName, 20 IN PEVENTLOGRECORD pevlr, 21 OUT PWCHAR EventText); 22 23 24 typedef struct _DETAILDATA 25 { 26 PEVENTLOGFILTER EventLogFilter; 27 28 BOOL bDisplayWords; 29 HFONT hMonospaceFont; 30 31 INT cxMin, cyMin; 32 INT cxOld, cyOld; 33 POINT scPos; 34 } DETAILDATA, *PDETAILDATA; 35 36 37 static 38 VOID 39 DisplayEvent(HWND hDlg, PEVENTLOGFILTER EventLogFilter) 40 { 41 WCHAR szEventType[MAX_PATH]; 42 WCHAR szTime[MAX_PATH]; 43 WCHAR szDate[MAX_PATH]; 44 WCHAR szUser[MAX_PATH]; 45 WCHAR szComputer[MAX_PATH]; 46 WCHAR szSource[MAX_PATH]; 47 WCHAR szCategory[MAX_PATH]; 48 WCHAR szEventID[MAX_PATH]; 49 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER]; 50 BOOL bEventData = FALSE; 51 LVITEMW li; 52 PEVENTLOGRECORD pevlr; 53 int iIndex; 54 55 /* Get index of selected item */ 56 iIndex = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED | LVNI_FOCUSED); 57 if (iIndex == -1) 58 { 59 MessageBoxW(hDlg, 60 L"No Items in ListView", 61 L"Error", 62 MB_OK | MB_ICONINFORMATION); 63 return; 64 } 65 66 li.mask = LVIF_PARAM; 67 li.iItem = iIndex; 68 li.iSubItem = 0; 69 70 ListView_GetItem(hwndListView, &li); 71 72 pevlr = (PEVENTLOGRECORD)li.lParam; 73 74 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, ARRAYSIZE(szEventType)); 75 ListView_GetItemText(hwndListView, iIndex, 1, szDate, ARRAYSIZE(szDate)); 76 ListView_GetItemText(hwndListView, iIndex, 2, szTime, ARRAYSIZE(szTime)); 77 ListView_GetItemText(hwndListView, iIndex, 3, szSource, ARRAYSIZE(szSource)); 78 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, ARRAYSIZE(szCategory)); 79 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, ARRAYSIZE(szEventID)); 80 ListView_GetItemText(hwndListView, iIndex, 6, szUser, ARRAYSIZE(szUser)); 81 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, ARRAYSIZE(szComputer)); 82 83 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate); 84 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime); 85 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser); 86 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource); 87 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer); 88 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory); 89 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID); 90 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType); 91 92 bEventData = (pevlr->DataLength > 0); 93 EnableDlgItem(hDlg, IDC_BYTESRADIO, bEventData); 94 EnableDlgItem(hDlg, IDC_WORDRADIO, bEventData); 95 96 // FIXME: At the moment we support only one event log in the filter 97 GetEventMessage(EventLogFilter->EventLogs[0]->LogName, szSource, pevlr, szEventText); 98 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText); 99 } 100 101 static 102 UINT 103 PrintByteDataLine(PWCHAR pBuffer, UINT uOffset, PBYTE pData, UINT uLength) 104 { 105 PWCHAR p = pBuffer; 106 UINT n, i, r = 0; 107 108 if (uOffset != 0) 109 { 110 n = swprintf(p, L"\r\n"); 111 p += n; 112 r += n; 113 } 114 115 n = swprintf(p, L"%04lx:", uOffset); 116 p += n; 117 r += n; 118 119 for (i = 0; i < uLength; i++) 120 { 121 n = swprintf(p, L" %02x", pData[i]); 122 p += n; 123 r += n; 124 } 125 126 for (i = 0; i < 9 - uLength; i++) 127 { 128 n = swprintf(p, L" "); 129 p += n; 130 r += n; 131 } 132 133 for (i = 0; i < uLength; i++) 134 { 135 // NOTE: Normally iswprint should return FALSE for tabs... 136 n = swprintf(p, L"%c", (iswprint(pData[i]) && (pData[i] != L'\t')) ? pData[i] : L'.'); 137 p += n; 138 r += n; 139 } 140 141 return r; 142 } 143 144 static 145 UINT 146 PrintWordDataLine(PWCHAR pBuffer, UINT uOffset, PULONG pData, UINT uLength) 147 { 148 PWCHAR p = pBuffer; 149 UINT n, i, r = 0; 150 151 if (uOffset != 0) 152 { 153 n = swprintf(p, L"\r\n"); 154 p += n; 155 r += n; 156 } 157 158 n = swprintf(p, L"%04lx:", uOffset); 159 p += n; 160 r += n; 161 162 for (i = 0; i < uLength / sizeof(ULONG); i++) 163 { 164 n = swprintf(p, L" %08lx", pData[i]); 165 p += n; 166 r += n; 167 } 168 169 /* Display the remaining bytes if uLength was not a multiple of sizeof(ULONG) */ 170 for (i = (uLength / sizeof(ULONG)) * sizeof(ULONG); i < uLength; i++) 171 { 172 n = swprintf(p, L" %02x", ((PBYTE)pData)[i]); 173 p += n; 174 r += n; 175 } 176 177 return r; 178 } 179 180 static 181 VOID 182 DisplayEventData(HWND hDlg, BOOL bDisplayWords) 183 { 184 LVITEMW li; 185 PEVENTLOGRECORD pevlr; 186 int iIndex; 187 188 LPBYTE pData; 189 UINT i, uOffset; 190 UINT uBufferSize, uLineLength; 191 PWCHAR pTextBuffer, pLine; 192 193 /* Get index of selected item */ 194 iIndex = ListView_GetNextItem(hwndListView, -1, LVNI_SELECTED | LVNI_FOCUSED); 195 if (iIndex == -1) 196 { 197 MessageBoxW(hDlg, 198 L"No Items in ListView", 199 L"Error", 200 MB_OK | MB_ICONINFORMATION); 201 return; 202 } 203 204 li.mask = LVIF_PARAM; 205 li.iItem = iIndex; 206 li.iSubItem = 0; 207 208 ListView_GetItem(hwndListView, &li); 209 210 pevlr = (PEVENTLOGRECORD)li.lParam; 211 if (pevlr->DataLength == 0) 212 { 213 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L""); 214 return; 215 } 216 217 if (bDisplayWords) 218 uBufferSize = ((pevlr->DataLength / 8) + 1) * 26 * sizeof(WCHAR); 219 else 220 uBufferSize = ((pevlr->DataLength / 8) + 1) * 43 * sizeof(WCHAR); 221 222 pTextBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uBufferSize); 223 if (!pTextBuffer) 224 return; 225 226 pLine = pTextBuffer; 227 uOffset = 0; 228 229 for (i = 0; i < pevlr->DataLength / 8; i++) 230 { 231 pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset); 232 233 if (bDisplayWords) 234 uLineLength = PrintWordDataLine(pLine, uOffset, (PULONG)pData, 8); 235 else 236 uLineLength = PrintByteDataLine(pLine, uOffset, pData, 8); 237 pLine = pLine + uLineLength; 238 239 uOffset += 8; 240 } 241 242 if (pevlr->DataLength % 8 != 0) 243 { 244 pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset); 245 246 if (bDisplayWords) 247 PrintWordDataLine(pLine, uOffset, (PULONG)pData, pevlr->DataLength % 8); 248 else 249 PrintByteDataLine(pLine, uOffset, pData, pevlr->DataLength % 8); 250 } 251 252 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, pTextBuffer); 253 254 HeapFree(GetProcessHeap(), 0, pTextBuffer); 255 } 256 257 static 258 HFONT 259 CreateMonospaceFont(VOID) 260 { 261 LOGFONTW tmpFont = {0}; 262 HFONT hFont; 263 HDC hDC; 264 265 hDC = GetDC(NULL); 266 267 tmpFont.lfHeight = -MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72); 268 tmpFont.lfWeight = FW_NORMAL; 269 wcscpy(tmpFont.lfFaceName, L"Courier New"); 270 271 hFont = CreateFontIndirectW(&tmpFont); 272 273 ReleaseDC(NULL, hDC); 274 275 return hFont; 276 } 277 278 static 279 VOID 280 CopyEventEntry(HWND hWnd) 281 { 282 WCHAR tmpHeader[512]; 283 WCHAR szEventType[MAX_PATH]; 284 WCHAR szSource[MAX_PATH]; 285 WCHAR szCategory[MAX_PATH]; 286 WCHAR szEventID[MAX_PATH]; 287 WCHAR szDate[MAX_PATH]; 288 WCHAR szTime[MAX_PATH]; 289 WCHAR szUser[MAX_PATH]; 290 WCHAR szComputer[MAX_PATH]; 291 WCHAR evtDesc[EVENT_MESSAGE_EVENTTEXT_BUFFER]; 292 ULONG size = 0; 293 LPWSTR output; 294 HGLOBAL hMem; 295 296 /* Try to open the clipboard */ 297 if (!OpenClipboard(hWnd)) 298 return; 299 300 /* Get the formatted text needed to place the content into */ 301 size += LoadStringW(hInst, IDS_COPY, tmpHeader, ARRAYSIZE(tmpHeader)); 302 303 /* Grab all the information and get it ready for the clipboard */ 304 size += GetDlgItemTextW(hWnd, IDC_EVENTTYPESTATIC, szEventType, ARRAYSIZE(szEventType)); 305 size += GetDlgItemTextW(hWnd, IDC_EVENTSOURCESTATIC, szSource, ARRAYSIZE(szSource)); 306 size += GetDlgItemTextW(hWnd, IDC_EVENTCATEGORYSTATIC, szCategory, ARRAYSIZE(szCategory)); 307 size += GetDlgItemTextW(hWnd, IDC_EVENTIDSTATIC, szEventID, ARRAYSIZE(szEventID)); 308 size += GetDlgItemTextW(hWnd, IDC_EVENTDATESTATIC, szDate, ARRAYSIZE(szDate)); 309 size += GetDlgItemTextW(hWnd, IDC_EVENTTIMESTATIC, szTime, ARRAYSIZE(szTime)); 310 size += GetDlgItemTextW(hWnd, IDC_EVENTUSERSTATIC, szUser, ARRAYSIZE(szUser)); 311 size += GetDlgItemTextW(hWnd, IDC_EVENTCOMPUTERSTATIC, szComputer, ARRAYSIZE(szComputer)); 312 size += GetDlgItemTextW(hWnd, IDC_EVENTTEXTEDIT, evtDesc, ARRAYSIZE(evtDesc)); 313 314 size++; /* Null-termination */ 315 size *= sizeof(WCHAR); 316 317 /* 318 * Consolidate the information into one big piece and 319 * sort out the memory needed to write to the clipboard. 320 */ 321 hMem = GlobalAlloc(GMEM_MOVEABLE, size); 322 if (hMem == NULL) goto Quit; 323 324 output = GlobalLock(hMem); 325 if (output == NULL) 326 { 327 GlobalFree(hMem); 328 goto Quit; 329 } 330 331 StringCbPrintfW(output, size, 332 tmpHeader, szEventType, szSource, szCategory, szEventID, 333 szDate, szTime, szUser, szComputer, evtDesc); 334 335 GlobalUnlock(hMem); 336 337 /* We succeeded, empty the clipboard and write the data in it */ 338 EmptyClipboard(); 339 SetClipboardData(CF_UNICODETEXT, hMem); 340 341 Quit: 342 /* Close the clipboard once we are done with it */ 343 CloseClipboard(); 344 } 345 346 static VOID 347 OnScroll(HWND hDlg, PDETAILDATA pData, INT nBar, WORD sbCode) 348 { 349 RECT rect; 350 351 SCROLLINFO sInfo; 352 INT oldPos, Maximum; 353 PLONG pOriginXY; 354 355 ASSERT(nBar == SB_HORZ || nBar == SB_VERT); 356 357 GetClientRect(hDlg, &rect); 358 359 if (nBar == SB_HORZ) 360 { 361 Maximum = pData->cxMin - (rect.right-rect.left) /* pData->cxOld */; 362 pOriginXY = &pData->scPos.x; 363 } 364 else // if (nBar == SB_VERT) 365 { 366 Maximum = pData->cyMin - (rect.bottom-rect.top) /* pData->cyOld */; 367 pOriginXY = &pData->scPos.y; 368 } 369 370 /* Set scrollbar sizes */ 371 sInfo.cbSize = sizeof(sInfo); 372 sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS; 373 374 if (!GetScrollInfo(hDlg, nBar, &sInfo)) 375 return; 376 377 oldPos = sInfo.nPos; 378 379 switch (sbCode) 380 { 381 case SB_LINEUP: // SB_LINELEFT: 382 sInfo.nPos--; 383 break; 384 385 case SB_LINEDOWN: // SB_LINERIGHT: 386 sInfo.nPos++; 387 break; 388 389 case SB_PAGEUP: // SB_PAGELEFT: 390 sInfo.nPos -= sInfo.nPage; 391 break; 392 393 case SB_PAGEDOWN: // SB_PAGERIGHT: 394 sInfo.nPos += sInfo.nPage; 395 break; 396 397 case SB_THUMBTRACK: 398 sInfo.nPos = sInfo.nTrackPos; 399 break; 400 401 case SB_THUMBPOSITION: 402 sInfo.nPos = sInfo.nTrackPos; 403 break; 404 405 case SB_TOP: // SB_LEFT: 406 sInfo.nPos = sInfo.nMin; 407 break; 408 409 case SB_BOTTOM: // SB_RIGHT: 410 sInfo.nPos = sInfo.nMax; 411 break; 412 413 default: 414 break; 415 } 416 417 sInfo.nPos = min(max(sInfo.nPos, 0), Maximum); 418 419 if (oldPos != sInfo.nPos) 420 { 421 POINT scOldPos = pData->scPos; 422 423 /* We now modify pData->scPos */ 424 *pOriginXY = sInfo.nPos; 425 426 ScrollWindowEx(hDlg, 427 (scOldPos.x - pData->scPos.x), 428 (scOldPos.y - pData->scPos.y), 429 NULL, 430 NULL, 431 NULL, 432 NULL, 433 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN); 434 435 sInfo.fMask = SIF_POS; 436 SetScrollInfo(hDlg, nBar, &sInfo, TRUE); 437 438 // UpdateWindow(hDlg); 439 } 440 } 441 442 static VOID 443 OnSize(HWND hDlg, PDETAILDATA pData, INT cx, INT cy) 444 { 445 LONG_PTR dwStyle; 446 INT sbVXSize, sbHYSize; 447 SCROLLINFO sInfo; 448 POINT scOldPos; 449 HDWP hdwp; 450 HWND hItemWnd; 451 RECT rect; 452 INT y = 0; 453 454 if (!pData) 455 return; 456 457 dwStyle = GetWindowLongPtrW(hDlg, GWL_STYLE); 458 sbVXSize = GetSystemMetrics(SM_CXVSCROLL); 459 sbHYSize = GetSystemMetrics(SM_CYHSCROLL); 460 461 /* Compensate for existing scroll bars (because lParam values do not accommodate scroll bar) */ 462 if (dwStyle & WS_HSCROLL) cy += sbHYSize; // Window currently has a horizontal scrollbar 463 if (dwStyle & WS_VSCROLL) cx += sbVXSize; // Window currently has a vertical scrollbar 464 465 /* Compensate for added scroll bars in window */ 466 if (cx < pData->cxMin) cy -= sbHYSize; // Window will have a horizontal scroll bar 467 if (cy < pData->cyMin) cx -= sbVXSize; // Window will have a vertical scroll bar 468 469 /* Set scrollbar sizes */ 470 sInfo.cbSize = sizeof(sInfo); 471 472 sInfo.fMask = SIF_POS; 473 if (GetScrollInfo(hDlg, SB_VERT, &sInfo)) 474 scOldPos.y = sInfo.nPos; 475 else 476 scOldPos.y = pData->scPos.y; 477 478 sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; 479 sInfo.nMin = 0; 480 if (pData->cyMin > cy) 481 { 482 sInfo.nMax = pData->cyMin - 1; 483 sInfo.nPage = cy; 484 sInfo.nPos = pData->scPos.y; 485 SetScrollInfo(hDlg, SB_VERT, &sInfo, TRUE); 486 487 /* Display the scrollbar if needed */ 488 if (!(dwStyle & WS_VSCROLL)) 489 ShowScrollBar(hDlg, SB_VERT, TRUE); 490 } 491 else 492 { 493 scOldPos.y = 0; 494 495 sInfo.nMax = pData->cyMin - 1; 496 sInfo.nPage = cy; 497 sInfo.nPos = pData->scPos.y; 498 sInfo.nPos = scOldPos.y; 499 SetScrollInfo(hDlg, SB_VERT, &sInfo, TRUE); 500 501 ShowScrollBar(hDlg, SB_VERT, FALSE); 502 503 rect.left = cx - sbVXSize; 504 rect.right = cx; 505 rect.top = 0; 506 rect.bottom = cy; 507 InvalidateRect(hDlg, &rect, TRUE); 508 } 509 510 sInfo.fMask = SIF_POS; 511 if (GetScrollInfo(hDlg, SB_HORZ, &sInfo)) 512 scOldPos.x = sInfo.nPos; 513 else 514 scOldPos.x = pData->scPos.x; 515 516 sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; 517 sInfo.nMin = 0; 518 if (pData->cxMin > cx) 519 { 520 sInfo.nMax = pData->cxMin - 1; 521 sInfo.nPage = cx; 522 sInfo.nPos = pData->scPos.x; 523 SetScrollInfo(hDlg, SB_HORZ, &sInfo, TRUE); 524 525 /* Display the scrollbar if needed */ 526 if (!(dwStyle & WS_HSCROLL)) 527 ShowScrollBar(hDlg, SB_HORZ, TRUE); 528 } 529 else 530 { 531 scOldPos.x = 0; 532 533 sInfo.nMax = pData->cxMin - 1; 534 sInfo.nPage = cx; 535 sInfo.nPos = pData->scPos.x; 536 sInfo.nPos = scOldPos.x; 537 SetScrollInfo(hDlg, SB_HORZ, &sInfo, TRUE); 538 539 ShowScrollBar(hDlg, SB_HORZ, FALSE); 540 541 rect.left = 0; 542 rect.right = cx; 543 rect.top = cy - sbHYSize; 544 rect.bottom = cy; 545 InvalidateRect(hDlg, &rect, TRUE); 546 } 547 548 if ((scOldPos.x != pData->scPos.x) || (scOldPos.y != pData->scPos.y)) 549 { 550 ScrollWindowEx(hDlg, 551 // (scOldPos.x - pData->scPos.x), 552 (pData->scPos.x - scOldPos.x), 553 // (scOldPos.y - pData->scPos.y), 554 (pData->scPos.y - scOldPos.y), 555 NULL, 556 NULL, 557 NULL, 558 NULL, 559 SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN); 560 561 pData->scPos = scOldPos; 562 } 563 564 // /* Adjust the start of the visible area if we are attempting to show nonexistent areas */ 565 // if ((pData->cxMin - pData->scPos.x) < cx) pData->scPos.x = pData->cxMin - cx; 566 // if ((pData->cyMin - pData->scPos.y) < cy) pData->scPos.y = pData->cyMin - cy; 567 // // InvalidateRect(GuiData->hWindow, NULL, TRUE); 568 569 /* Forbid resizing the control smaller than its minimal size */ 570 if (cx < pData->cxMin) cx = pData->cxMin; 571 if (cy < pData->cyMin) cy = pData->cyMin; 572 573 if ((cx != pData->cxOld) || (cy != pData->cyOld)) 574 { 575 hdwp = BeginDeferWindowPos(8); 576 577 /* Move the edit boxes */ 578 579 GetWindowRect(hDlg, &rect); 580 581 hItemWnd = GetDlgItem(hDlg, IDC_EVENTTEXTEDIT); 582 GetWindowRect(hItemWnd, &rect); 583 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 584 // OffsetRect(&rect, 0, y); 585 // y += (cy - pData->cyOld) / 2 ; // + (cy - pData->cyOld) % 2; 586 /** y += (cy - pData->cyOld) / 2 ; // + (cy - pData->cyOld) % 2; **/ 587 if (cy >= pData->cyOld) 588 y += (cy - pData->cyOld) / 2 + (cy - pData->cyOld) % 2; 589 else 590 y -= (pData->cyOld - cy) / 2 + (pData->cyOld - cy) % 2; 591 592 if (hdwp) 593 hdwp = DeferWindowPos(hdwp, 594 hItemWnd, 595 0, 596 rect.left, rect.top, 597 (rect.right - rect.left) + (cx - pData->cxOld), 598 (rect.bottom - rect.top) + y, 599 /** SWP_NOMOVE | **/ SWP_NOZORDER | SWP_NOACTIVATE); 600 601 hItemWnd = GetDlgItem(hDlg, IDC_DETAILS_STATIC); 602 GetWindowRect(hItemWnd, &rect); 603 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 604 // OffsetRect(&rect, 0, y); 605 606 if (hdwp) 607 hdwp = DeferWindowPos(hdwp, 608 hItemWnd, 609 0, 610 rect.left, rect.top + y, 611 0, 0, 612 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 613 614 hItemWnd = GetDlgItem(hDlg, IDC_BYTESRADIO); 615 GetWindowRect(hItemWnd, &rect); 616 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 617 // OffsetRect(&rect, 0, y); 618 619 if (hdwp) 620 hdwp = DeferWindowPos(hdwp, 621 hItemWnd, 622 0, 623 rect.left, rect.top + y, 624 0, 0, 625 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 626 627 hItemWnd = GetDlgItem(hDlg, IDC_WORDRADIO); 628 GetWindowRect(hItemWnd, &rect); 629 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 630 // OffsetRect(&rect, 0, y); 631 632 if (hdwp) 633 hdwp = DeferWindowPos(hdwp, 634 hItemWnd, 635 0, 636 rect.left, rect.top + y, 637 0, 0, 638 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 639 640 hItemWnd = GetDlgItem(hDlg, IDC_EVENTDATAEDIT); 641 GetWindowRect(hItemWnd, &rect); 642 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 643 // OffsetRect(&rect, 0, y); 644 // // y -= (cy - pData->cyOld) % 2; 645 646 if (hdwp) 647 hdwp = DeferWindowPos(hdwp, 648 hItemWnd, 649 0, 650 rect.left, rect.top + y, 651 (rect.right - rect.left) + (cx - pData->cxOld), 652 (rect.bottom - rect.top) + y, 653 SWP_NOZORDER | SWP_NOACTIVATE); 654 655 /* Move the buttons */ 656 657 hItemWnd = GetDlgItem(hDlg, IDC_PREVIOUS); 658 GetWindowRect(hItemWnd, &rect); 659 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 660 661 if (hdwp) 662 hdwp = DeferWindowPos(hdwp, 663 hItemWnd, 664 0, 665 rect.left + (cx - pData->cxOld), 666 rect.top, 667 0, 0, 668 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 669 670 hItemWnd = GetDlgItem(hDlg, IDC_NEXT); 671 GetWindowRect(hItemWnd, &rect); 672 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 673 674 if (hdwp) 675 hdwp = DeferWindowPos(hdwp, 676 hItemWnd, 677 0, 678 rect.left + (cx - pData->cxOld), 679 rect.top, 680 0, 0, 681 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 682 683 hItemWnd = GetDlgItem(hDlg, IDC_COPY); 684 GetWindowRect(hItemWnd, &rect); 685 MapWindowPoints(HWND_DESKTOP /*NULL*/, hDlg, (LPPOINT)&rect, sizeof(RECT)/sizeof(POINT)); 686 687 if (hdwp) 688 hdwp = DeferWindowPos(hdwp, 689 hItemWnd, 690 0, 691 rect.left + (cx - pData->cxOld), 692 rect.top, 693 0, 0, 694 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 695 696 if (hdwp) 697 EndDeferWindowPos(hdwp); 698 699 pData->cxOld = cx; 700 pData->cyOld = cy; 701 } 702 } 703 704 static 705 VOID 706 InitDetailsDlgCtrl(HWND hDlg, PDETAILDATA pData) 707 { 708 DWORD dwMask; 709 710 HANDLE nextIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_NEXT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); 711 HANDLE prevIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_PREV), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); 712 HANDLE copyIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_COPY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); 713 714 SendDlgItemMessageW(hDlg, IDC_NEXT, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)nextIcon); 715 SendDlgItemMessageW(hDlg, IDC_PREVIOUS, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)prevIcon); 716 SendDlgItemMessageW(hDlg, IDC_COPY, BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)copyIcon); 717 718 /* Set the default read-only RichEdit color */ 719 SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_3DFACE)); 720 721 /* Enable RichEdit coloured and underlined links */ 722 dwMask = SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_GETEVENTMASK, 0, 0); 723 SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_SETEVENTMASK, 0, dwMask | ENM_LINK | ENM_MOUSEEVENTS); 724 725 /* 726 * Activate automatic URL recognition by the RichEdit control. For more information, see: 727 * https://blogs.msdn.microsoft.com/murrays/2009/08/31/automatic-richedit-hyperlinks/ 728 * https://blogs.msdn.microsoft.com/murrays/2009/09/24/richedit-friendly-name-hyperlinks/ 729 * https://msdn.microsoft.com/en-us/library/windows/desktop/bb787991(v=vs.85).aspx 730 */ 731 SendDlgItemMessageW(hDlg, IDC_EVENTTEXTEDIT, EM_AUTOURLDETECT, AURL_ENABLEURL /* | AURL_ENABLEEAURLS */, 0); 732 733 /* Note that the RichEdit control never gets themed under WinXP+. One would have to write code to simulate Edit-control theming */ 734 735 SendDlgItemMessageW(hDlg, pData->bDisplayWords ? IDC_WORDRADIO : IDC_BYTESRADIO, BM_SETCHECK, BST_CHECKED, 0); 736 SendDlgItemMessageW(hDlg, IDC_EVENTDATAEDIT, WM_SETFONT, (WPARAM)pData->hMonospaceFont, (LPARAM)TRUE); 737 } 738 739 /* Message handler for Event Details control */ 740 static 741 INT_PTR CALLBACK 742 EventDetailsCtrl(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) 743 { 744 PDETAILDATA pData; 745 746 pData = (PDETAILDATA)GetWindowLongPtrW(hDlg, DWLP_USER); 747 748 switch (uMsg) 749 { 750 case WM_INITDIALOG: 751 { 752 RECT rect; 753 754 pData = (PDETAILDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pData)); 755 if (!pData) 756 { 757 EndDialog(hDlg, 0); 758 return (INT_PTR)TRUE; 759 } 760 SetWindowLongPtrW(hDlg, DWLP_USER, (LONG_PTR)pData); 761 762 pData->EventLogFilter = (PEVENTLOGFILTER)lParam; 763 pData->bDisplayWords = FALSE; 764 pData->hMonospaceFont = CreateMonospaceFont(); 765 766 GetClientRect(hDlg, &rect); 767 pData->cxOld = pData->cxMin = rect.right - rect.left; 768 pData->cyOld = pData->cyMin = rect.bottom - rect.top; 769 pData->scPos.x = pData->scPos.y = 0; 770 771 InitDetailsDlgCtrl(hDlg, pData); 772 773 #if 0 774 /* Show event info on dialog box */ 775 DisplayEvent(hDlg, pData->EventLogFilter); 776 DisplayEventData(hDlg, pData->bDisplayWords); 777 #endif 778 779 // OnSize(hDlg, pData, pData->cxOld, pData->cyOld); 780 return (INT_PTR)TRUE; 781 } 782 783 case WM_DESTROY: 784 if (pData) 785 { 786 if (pData->hMonospaceFont) 787 DeleteObject(pData->hMonospaceFont); 788 HeapFree(GetProcessHeap(), 0, pData); 789 } 790 return (INT_PTR)TRUE; 791 792 case EVT_SETFILTER: 793 pData->EventLogFilter = (PEVENTLOGFILTER)lParam; 794 return (INT_PTR)TRUE; 795 796 case EVT_DISPLAY: 797 if (pData->EventLogFilter) 798 { 799 /* Show event info on dialog box */ 800 DisplayEvent(hDlg, pData->EventLogFilter); 801 DisplayEventData(hDlg, pData->bDisplayWords); 802 } 803 return (INT_PTR)TRUE; 804 805 case WM_COMMAND: 806 switch (LOWORD(wParam)) 807 { 808 case IDC_PREVIOUS: 809 { 810 SendMessageW(hwndListView, WM_KEYDOWN, VK_UP, 0); 811 812 /* Show event info on dialog box */ 813 if (pData->EventLogFilter) 814 { 815 DisplayEvent(hDlg, pData->EventLogFilter); 816 DisplayEventData(hDlg, pData->bDisplayWords); 817 } 818 return (INT_PTR)TRUE; 819 } 820 821 case IDC_NEXT: 822 { 823 SendMessageW(hwndListView, WM_KEYDOWN, VK_DOWN, 0); 824 825 /* Show event info on dialog box */ 826 if (pData->EventLogFilter) 827 { 828 DisplayEvent(hDlg, pData->EventLogFilter); 829 DisplayEventData(hDlg, pData->bDisplayWords); 830 } 831 return (INT_PTR)TRUE; 832 } 833 834 case IDC_COPY: 835 if (pData->EventLogFilter) 836 CopyEventEntry(hDlg); 837 return (INT_PTR)TRUE; 838 839 case IDC_BYTESRADIO: 840 if (pData->EventLogFilter) 841 { 842 pData->bDisplayWords = FALSE; 843 DisplayEventData(hDlg, pData->bDisplayWords); 844 } 845 return (INT_PTR)TRUE; 846 847 case IDC_WORDRADIO: 848 if (pData->EventLogFilter) 849 { 850 pData->bDisplayWords = TRUE; 851 DisplayEventData(hDlg, pData->bDisplayWords); 852 } 853 return (INT_PTR)TRUE; 854 855 default: 856 break; 857 } 858 break; 859 860 case WM_NOTIFY: 861 switch (((LPNMHDR)lParam)->code) 862 { 863 case EN_LINK: 864 // TODO: Act on the activated RichEdit link! 865 break; 866 } 867 break; 868 869 case WM_HSCROLL: 870 OnScroll(hDlg, pData, SB_HORZ, LOWORD(wParam)); 871 SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0); 872 return (INT_PTR)TRUE; 873 874 case WM_VSCROLL: 875 OnScroll(hDlg, pData, SB_VERT, LOWORD(wParam)); 876 SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0); 877 return (INT_PTR)TRUE; 878 879 case WM_SIZE: 880 OnSize(hDlg, pData, LOWORD(lParam), HIWORD(lParam)); 881 SetWindowLongPtrW(hDlg, DWLP_MSGRESULT, 0); 882 return (INT_PTR)TRUE; 883 } 884 885 return (INT_PTR)FALSE; 886 } 887 888 HWND 889 CreateEventDetailsCtrl(HINSTANCE hInstance, 890 HWND hParentWnd, 891 LPARAM lParam) 892 { 893 return CreateDialogParamW(hInstance, 894 MAKEINTRESOURCEW(IDD_EVENTDETAILS_CTRL), 895 hParentWnd, EventDetailsCtrl, lParam); 896 } 897