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