[EVENTVWR]
[reactos.git] / reactos / base / applications / mscutils / eventvwr / eventvwr.c
1 /*
2 * ReactOS Win32 Applications
3 * Copyright (C) 2007 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * COPYRIGHT : See COPYING in the top level directory
21 * PROJECT : Event Log Viewer
22 * FILE : eventvwr.c
23 * PROGRAMMER: Marc Piulachs (marc.piulachs at codexchange [dot] net)
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <windef.h>
30 #include <winbase.h>
31 #include <winuser.h>
32 #include <wingdi.h>
33 #include <winnls.h>
34 #include <winreg.h>
35 #include <commctrl.h>
36 #include <commdlg.h>
37 #include <strsafe.h>
38
39 #include "resource.h"
40
41 typedef struct _DETAILDATA
42 {
43 BOOL bDisplayWords;
44 HFONT hMonospaceFont;
45 } DETAILDATA, *PDETAILDATA;
46
47 static const WCHAR szWindowClass[] = L"EVENTVWR"; /* the main window class name */
48 static const WCHAR EVENTLOG_BASE_KEY[] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
49
50 // MessageFile message buffer size
51 #define EVENT_MESSAGE_EVENTTEXT_BUFFER 1024*10
52 #define EVENT_MESSAGE_FILE_BUFFER 1024*10
53 #define EVENT_DLL_SEPARATOR L";"
54 #define EVENT_CATEGORY_MESSAGE_FILE L"CategoryMessageFile"
55 #define EVENT_MESSAGE_FILE L"EventMessageFile"
56 #define EVENT_PARAMETER_MESSAGE_FILE L"ParameterMessageFile"
57
58 #define MAX_LOADSTRING 255
59 #define ENTRY_SIZE 2056
60
61 /* Globals */
62 HINSTANCE hInst; /* current instance */
63 WCHAR szTitle[MAX_LOADSTRING]; /* The title bar text */
64 WCHAR szTitleTemplate[MAX_LOADSTRING]; /* The logged-on title bar text */
65 WCHAR szSaveFilter[MAX_LOADSTRING]; /* Filter Mask for the save Dialog */
66 HWND hwndMainWindow; /* Main window */
67 HWND hwndListView; /* ListView control */
68 HWND hwndStatus; /* Status bar */
69 HMENU hMainMenu; /* The application's main menu */
70 WCHAR szStatusBarTemplate[MAX_LOADSTRING]; /* The status bar text */
71 PEVENTLOGRECORD *g_RecordPtrs = NULL;
72 DWORD g_TotalRecords = 0;
73 OPENFILENAMEW sfn;
74
75 LPWSTR lpSourceLogName = NULL;
76 LPWSTR lpComputerName = NULL;
77
78 DWORD dwNumLogs = 0;
79 LPWSTR* LogNames;
80
81 /* Forward declarations of functions included in this code module: */
82 ATOM MyRegisterClass(HINSTANCE hInstance);
83 BOOL InitInstance(HINSTANCE, int);
84 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
85 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
86 INT_PTR CALLBACK EventDetails(HWND, UINT, WPARAM, LPARAM);
87 static INT_PTR CALLBACK StatusMessageWindowProc (HWND, UINT, WPARAM, LPARAM);
88
89
90 int APIENTRY
91 wWinMain(HINSTANCE hInstance,
92 HINSTANCE hPrevInstance,
93 LPWSTR lpCmdLine,
94 int nCmdShow)
95 {
96 MSG msg;
97 HACCEL hAccelTable;
98 INITCOMMONCONTROLSEX iccx;
99
100 UNREFERENCED_PARAMETER(hPrevInstance);
101 UNREFERENCED_PARAMETER(lpCmdLine);
102
103 /* Whenever any of the common controls are used in your app,
104 * you must call InitCommonControlsEx() to register the classes
105 * for those controls. */
106 iccx.dwSize = sizeof(iccx);
107 iccx.dwICC = ICC_LISTVIEW_CLASSES;
108 InitCommonControlsEx(&iccx);
109
110 /* Initialize global strings */
111 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, ARRAYSIZE(szTitle));
112 LoadStringW(hInstance, IDS_APP_TITLE_EX, szTitleTemplate, ARRAYSIZE(szTitleTemplate));
113 LoadStringW(hInstance, IDS_STATUS_MSG, szStatusBarTemplate, ARRAYSIZE(szStatusBarTemplate));
114 MyRegisterClass(hInstance);
115
116 /* Perform application initialization: */
117 if (!InitInstance(hInstance, nCmdShow))
118 {
119 return FALSE;
120 }
121
122 hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDA_EVENTVWR));
123
124 /* Main message loop: */
125 while (GetMessageW(&msg, NULL, 0, 0))
126 {
127 if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg))
128 {
129 TranslateMessage(&msg);
130 DispatchMessageW(&msg);
131 }
132 }
133
134 return (int)msg.wParam;
135 }
136
137 static void FreeRecords(void)
138 {
139 DWORD iIndex;
140
141 if (!g_RecordPtrs)
142 return;
143
144 for (iIndex = 0; iIndex < g_TotalRecords; iIndex++)
145 HeapFree(GetProcessHeap(), 0, g_RecordPtrs[iIndex]);
146 HeapFree(GetProcessHeap(), 0, g_RecordPtrs);
147 g_RecordPtrs = NULL;
148 }
149
150 VOID
151 ShowLastWin32Error(VOID)
152 {
153 DWORD dwError;
154 LPWSTR lpMessageBuffer;
155
156 dwError = GetLastError();
157 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
158 NULL,
159 dwError,
160 0,
161 (LPWSTR)&lpMessageBuffer,
162 0,
163 NULL);
164
165 MessageBoxW(hwndMainWindow, lpMessageBuffer, szTitle, MB_OK | MB_ICONERROR);
166 LocalFree(lpMessageBuffer);
167 }
168
169 VOID
170 EventTimeToSystemTime(DWORD EventTime,
171 SYSTEMTIME *pSystemTime)
172 {
173 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
174 FILETIME ftLocal;
175 union
176 {
177 FILETIME ft;
178 ULONGLONG ll;
179 } u1970, uUCT;
180
181 uUCT.ft.dwHighDateTime = 0;
182 uUCT.ft.dwLowDateTime = EventTime;
183 SystemTimeToFileTime(&st1970, &u1970.ft);
184 uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
185 FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
186 FileTimeToSystemTime(&ftLocal, pSystemTime);
187 }
188
189
190 void
191 TrimNulls(LPWSTR s)
192 {
193 WCHAR *c;
194
195 if (s != NULL)
196 {
197 c = s + wcslen(s) - 1;
198 while (c >= s && iswspace(*c))
199 --c;
200 *++c = L'\0';
201 }
202 }
203
204
205 BOOL
206 GetEventMessageFileDLL(IN LPCWSTR lpLogName,
207 IN LPCWSTR SourceName,
208 IN LPCWSTR EntryName,
209 OUT PWCHAR ExpandedName)
210 {
211 DWORD dwSize;
212 WCHAR szModuleName[MAX_PATH];
213 WCHAR szKeyName[MAX_PATH];
214 HKEY hAppKey = NULL;
215 HKEY hSourceKey = NULL;
216 BOOL bReturn = FALSE;
217
218 StringCbCopyW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\");
219 StringCbCatW(szKeyName, sizeof(szKeyName), lpLogName);
220
221 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
222 szKeyName,
223 0,
224 KEY_READ,
225 &hAppKey) == ERROR_SUCCESS)
226 {
227 if (RegOpenKeyExW(hAppKey,
228 SourceName,
229 0,
230 KEY_READ,
231 &hSourceKey) == ERROR_SUCCESS)
232 {
233 dwSize = sizeof(szModuleName);
234 if (RegQueryValueExW(hSourceKey,
235 EntryName,
236 NULL,
237 NULL,
238 (LPBYTE)szModuleName,
239 &dwSize) == ERROR_SUCCESS)
240 {
241 /* Returns a string containing the requested substituted environment variable. */
242 ExpandEnvironmentStringsW(szModuleName, ExpandedName, MAX_PATH);
243
244 /* Successful */
245 bReturn = TRUE;
246 }
247 }
248 }
249 else
250 {
251 ShowLastWin32Error();
252 }
253
254 if (hSourceKey != NULL)
255 RegCloseKey(hSourceKey);
256
257 if (hAppKey != NULL)
258 RegCloseKey(hAppKey);
259
260 return bReturn;
261 }
262
263
264 BOOL
265 GetEventCategory(IN LPCWSTR KeyName,
266 IN LPCWSTR SourceName,
267 IN EVENTLOGRECORD *pevlr,
268 OUT PWCHAR CategoryName)
269 {
270 BOOL Success = FALSE;
271 HMODULE hLibrary = NULL;
272 WCHAR szMessageDLL[MAX_PATH];
273 LPWSTR lpMsgBuf = NULL;
274
275 if (!GetEventMessageFileDLL(KeyName, SourceName, EVENT_CATEGORY_MESSAGE_FILE, szMessageDLL))
276 goto Quit;
277
278 hLibrary = LoadLibraryExW(szMessageDLL, NULL,
279 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
280 if (hLibrary == NULL)
281 goto Quit;
282
283 /* Retrieve the message string. */
284 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
285 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
286 hLibrary,
287 pevlr->EventCategory,
288 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
289 (LPWSTR)&lpMsgBuf,
290 EVENT_MESSAGE_FILE_BUFFER,
291 NULL) != 0)
292 {
293 /* Trim the string */
294 TrimNulls(lpMsgBuf);
295
296 /* Copy the category name */
297 StringCchCopyW(CategoryName, MAX_PATH, lpMsgBuf);
298 }
299 else
300 {
301 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
302 }
303
304 /* Free the buffer allocated by FormatMessage */
305 if (lpMsgBuf)
306 LocalFree(lpMsgBuf);
307
308 if (hLibrary != NULL)
309 FreeLibrary(hLibrary);
310
311 Success = TRUE;
312
313 Quit:
314 if (!Success)
315 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
316
317 return Success;
318 }
319
320
321 BOOL
322 GetEventMessage(IN LPCWSTR KeyName,
323 IN LPCWSTR SourceName,
324 IN EVENTLOGRECORD *pevlr,
325 OUT PWCHAR EventText)
326 {
327 BOOL Success = FALSE;
328 DWORD i;
329 HMODULE hLibrary = NULL;
330 WCHAR SourceModuleName[1000];
331 WCHAR ParameterModuleName[1000];
332 BOOL IsParamModNameCached = FALSE;
333 LPWSTR lpMsgBuf = NULL;
334 WCHAR szStringIDNotFound[MAX_LOADSTRING];
335 LPWSTR szDll;
336 LPWSTR szMessage;
337 LPWSTR *szArguments;
338
339 /* NOTE: GetEventMessageFileDLL can return a comma-separated list of DLLs */
340
341 if (!GetEventMessageFileDLL(KeyName, SourceName, EVENT_MESSAGE_FILE, SourceModuleName))
342 {
343 // goto Quit;
344 return FALSE;
345 }
346
347 /* Get the event message */
348 szMessage = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
349
350 /* Allocate space for parameters */
351 szArguments = HeapAlloc(GetProcessHeap(), 0, pevlr->NumStrings * sizeof(LPVOID));
352 if (!szArguments)
353 {
354 // goto Quit;
355 return FALSE;
356 }
357
358 for (i = 0; i < pevlr->NumStrings; i++)
359 {
360 if (wcsstr(szMessage, L"%%"))
361 {
362 if (!IsParamModNameCached && GetEventMessageFileDLL(KeyName, SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
363 {
364 /* Now that the parameter file list is loaded, no need to reload it at the next run! */
365 IsParamModNameCached = TRUE;
366
367 /* Not yet support for reading messages from parameter message DLL */
368 }
369 }
370
371 szArguments[i] = szMessage;
372 szMessage += wcslen(szMessage) + 1;
373 }
374
375 /* Loop through the list of event message DLLs */
376 szDll = wcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
377 while ((szDll != NULL) && (!Success))
378 {
379 hLibrary = LoadLibraryExW(szDll, NULL,
380 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
381 if (hLibrary == NULL)
382 {
383 /* The DLL could not be loaded try the next one (if any) */
384 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
385 continue;
386 }
387
388 /* Retrieve the message string. */
389 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
390 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
391 hLibrary,
392 pevlr->EventID,
393 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
394 (LPWSTR)&lpMsgBuf,
395 0,
396 (va_list*)szArguments) == 0)
397 {
398 /* We haven't found the string, get next DLL (if any) */
399 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
400 }
401 else if (lpMsgBuf)
402 {
403 /* The ID was found and the message was formated */
404 Success = TRUE;
405
406 /* Trim the string */
407 TrimNulls((LPWSTR)lpMsgBuf);
408
409 /* Copy the event text */
410 StringCchCopyW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, lpMsgBuf);
411 }
412
413 /* Free the buffer allocated by FormatMessage */
414 if (lpMsgBuf)
415 LocalFree(lpMsgBuf);
416
417 FreeLibrary(hLibrary);
418 }
419
420 HeapFree(GetProcessHeap(), 0, szArguments);
421
422 // Quit:
423 if (!Success)
424 {
425 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, ARRAYSIZE(szStringIDNotFound));
426 StringCchPrintfW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
427 }
428
429 return Success;
430 }
431
432
433 VOID
434 GetEventType(IN WORD dwEventType,
435 OUT PWCHAR eventTypeText)
436 {
437 switch (dwEventType)
438 {
439 case EVENTLOG_ERROR_TYPE:
440 LoadStringW(hInst, IDS_EVENTLOG_ERROR_TYPE, eventTypeText, MAX_LOADSTRING);
441 break;
442 case EVENTLOG_WARNING_TYPE:
443 LoadStringW(hInst, IDS_EVENTLOG_WARNING_TYPE, eventTypeText, MAX_LOADSTRING);
444 break;
445 case EVENTLOG_INFORMATION_TYPE:
446 LoadStringW(hInst, IDS_EVENTLOG_INFORMATION_TYPE, eventTypeText, MAX_LOADSTRING);
447 break;
448 case EVENTLOG_AUDIT_SUCCESS:
449 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_SUCCESS, eventTypeText, MAX_LOADSTRING);
450 break;
451 case EVENTLOG_AUDIT_FAILURE:
452 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_FAILURE, eventTypeText, MAX_LOADSTRING);
453 break;
454 case EVENTLOG_SUCCESS:
455 LoadStringW(hInst, IDS_EVENTLOG_SUCCESS, eventTypeText, MAX_LOADSTRING);
456 break;
457 default:
458 LoadStringW(hInst, IDS_EVENTLOG_UNKNOWN_TYPE, eventTypeText, MAX_LOADSTRING);
459 break;
460 }
461 }
462
463 BOOL
464 GetEventUserName(EVENTLOGRECORD *pelr,
465 OUT PWCHAR pszUser)
466 {
467 PSID lpSid;
468 WCHAR szName[1024];
469 WCHAR szDomain[1024];
470 SID_NAME_USE peUse;
471 DWORD cbName = 1024;
472 DWORD cbDomain = 1024;
473
474 /* Point to the SID. */
475 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
476
477 /* User SID */
478 if (pelr->UserSidLength > 0)
479 {
480 if (LookupAccountSidW(NULL,
481 lpSid,
482 szName,
483 &cbName,
484 szDomain,
485 &cbDomain,
486 &peUse))
487 {
488 StringCchCopyW(pszUser, MAX_PATH, szName);
489 return TRUE;
490 }
491 }
492
493 return FALSE;
494 }
495
496
497 static DWORD WINAPI
498 ShowStatusMessageThread(IN LPVOID lpParameter)
499 {
500 HWND *phWnd = (HWND *)lpParameter;
501 HWND hWnd;
502 MSG Msg;
503
504 hWnd = CreateDialogParamW(hInst,
505 MAKEINTRESOURCEW(IDD_PROGRESSBOX),
506 GetDesktopWindow(),
507 StatusMessageWindowProc,
508 (LPARAM)NULL);
509 if (!hWnd)
510 return 0;
511
512 *phWnd = hWnd;
513
514 ShowWindow(hWnd, SW_SHOW);
515
516 /* Message loop for the Status window */
517 while (GetMessageW(&Msg, NULL, 0, 0))
518 {
519 TranslateMessage(&Msg);
520 DispatchMessageW(&Msg);
521 }
522
523 return 0;
524 }
525
526
527 BOOL
528 QueryEventMessages(LPWSTR lpMachineName,
529 LPWSTR lpLogName)
530 {
531 HWND hwndDlg = NULL;
532 HANDLE hEventLog;
533 EVENTLOGRECORD *pevlr;
534 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords = 0, dwCurrentRecord = 0, dwRecordsToRead = 0, dwFlags, dwMaxLength;
535 size_t cchRemaining;
536 LPWSTR lpSourceName;
537 LPWSTR lpComputerName;
538 BOOL bResult = TRUE; /* Read succeeded. */
539
540 WCHAR szWindowTitle[MAX_PATH];
541 WCHAR szStatusText[MAX_PATH];
542 WCHAR szLocalDate[MAX_PATH];
543 WCHAR szLocalTime[MAX_PATH];
544 WCHAR szEventID[MAX_PATH];
545 WCHAR szEventTypeText[MAX_LOADSTRING];
546 WCHAR szCategoryID[MAX_PATH];
547 WCHAR szUsername[MAX_PATH];
548 WCHAR szCategory[MAX_PATH];
549 PWCHAR lpTitleTemplateEnd;
550
551 SYSTEMTIME time;
552 LVITEMW lviEventItem;
553
554 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
555
556 /* Open the event log. */
557 hEventLog = OpenEventLogW(lpMachineName, lpLogName);
558 if (hEventLog == NULL)
559 {
560 ShowLastWin32Error();
561 return FALSE;
562 }
563
564 lpSourceLogName = lpLogName;
565 lpComputerName = lpMachineName;
566
567 /* Disable listview redraw */
568 SendMessageW(hwndListView, WM_SETREDRAW, FALSE, 0);
569
570 /* Clear the list view */
571 (void)ListView_DeleteAllItems(hwndListView);
572 FreeRecords();
573
574 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
575
576 /* Get the total number of event log records. */
577 GetNumberOfEventLogRecords(hEventLog, &dwTotalRecords);
578 g_TotalRecords = dwTotalRecords;
579
580 if (dwTotalRecords > 0)
581 {
582 EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_ENABLED);
583 EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_ENABLED);
584 }
585 else
586 {
587 EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_GRAYED);
588 EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_GRAYED);
589 }
590
591 g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(*g_RecordPtrs));
592
593 /* If we have at least 1000 records show the waiting dialog */
594 if (dwTotalRecords > 1000)
595 {
596 CloseHandle(CreateThread(NULL,
597 0,
598 ShowStatusMessageThread,
599 (LPVOID)&hwndDlg,
600 0,
601 NULL));
602 }
603
604 while (dwCurrentRecord < dwTotalRecords)
605 {
606 pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(*pevlr));
607 g_RecordPtrs[dwCurrentRecord] = pevlr;
608
609 bResult = ReadEventLogW(hEventLog, // Event log handle
610 dwFlags, // Sequential read
611 0, // Ignored for sequential read
612 pevlr, // Pointer to buffer
613 sizeof(*pevlr), // Size of buffer
614 &dwRead, // Number of bytes read
615 &dwNeeded); // Bytes in the next record
616 if ((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
617 {
618 HeapFree(GetProcessHeap(), 0, pevlr);
619 pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded);
620 g_RecordPtrs[dwCurrentRecord] = pevlr;
621
622 ReadEventLogW(hEventLog, // event log handle
623 dwFlags, // read flags
624 0, // offset; default is 0
625 pevlr, // pointer to buffer
626 dwNeeded, // size of buffer
627 &dwRead, // number of bytes read
628 &dwNeeded); // bytes in next record
629 }
630
631 while (dwRead > 0)
632 {
633 LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, ARRAYSIZE(szUsername));
634 LoadStringW(hInst, IDS_NONE, szCategory, ARRAYSIZE(szCategory));
635
636 // Get the event source name.
637 lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
638
639 // Get the computer name
640 lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR));
641
642 // Compute the event type
643 EventTimeToSystemTime(pevlr->TimeWritten, &time);
644
645 // Get the username that generated the event
646 GetEventUserName(pevlr, szUsername);
647
648 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, ARRAYSIZE(szLocalDate));
649 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &time, NULL, szLocalTime, ARRAYSIZE(szLocalTime));
650
651 GetEventType(pevlr->EventType, szEventTypeText);
652 GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory);
653
654 StringCbPrintfW(szEventID, sizeof(szEventID), L"%u", (pevlr->EventID & 0xFFFF));
655 StringCbPrintfW(szCategoryID, sizeof(szCategoryID), L"%u", pevlr->EventCategory);
656
657 lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
658 lviEventItem.iItem = 0;
659 lviEventItem.iSubItem = 0;
660 lviEventItem.lParam = (LPARAM)pevlr;
661 lviEventItem.pszText = szEventTypeText;
662
663 switch (pevlr->EventType)
664 {
665 case EVENTLOG_ERROR_TYPE:
666 lviEventItem.iImage = 2;
667 break;
668
669 case EVENTLOG_AUDIT_FAILURE:
670 lviEventItem.iImage = 2;
671 break;
672
673 case EVENTLOG_WARNING_TYPE:
674 lviEventItem.iImage = 1;
675 break;
676
677 case EVENTLOG_INFORMATION_TYPE:
678 lviEventItem.iImage = 0;
679 break;
680
681 case EVENTLOG_AUDIT_SUCCESS:
682 lviEventItem.iImage = 0;
683 break;
684
685 case EVENTLOG_SUCCESS:
686 lviEventItem.iImage = 0;
687 break;
688 }
689
690 lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem);
691
692 ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate);
693 ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime);
694 ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName);
695 ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory);
696 ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID);
697 ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername);
698 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName);
699
700 dwRead -= pevlr->Length;
701 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
702 }
703
704 dwRecordsToRead--;
705 dwCurrentRecord++;
706 }
707
708 // All events loaded
709 if (hwndDlg)
710 EndDialog(hwndDlg, 0);
711
712 StringCchPrintfExW(szWindowTitle,
713 ARRAYSIZE(szWindowTitle),
714 &lpTitleTemplateEnd,
715 &cchRemaining,
716 0,
717 szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */
718 /* lpComputerName can be NULL here if no records was read */
719 dwMaxLength = (DWORD)cchRemaining;
720 if (!lpComputerName)
721 GetComputerNameW(lpTitleTemplateEnd, &dwMaxLength);
722 else
723 StringCchCopyW(lpTitleTemplateEnd, dwMaxLength, lpComputerName);
724
725 StringCbPrintfW(szStatusText, sizeof(szStatusText), szStatusBarTemplate, lpLogName, dwTotalRecords);
726
727 // Update the status bar
728 SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
729
730 // Set the window title
731 SetWindowTextW(hwndMainWindow, szWindowTitle);
732
733 // Resume list view redraw
734 SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
735
736 // Close the event log.
737 CloseEventLog(hEventLog);
738
739 return TRUE;
740 }
741
742
743 VOID
744 SaveProtocol(VOID)
745 {
746 HANDLE hEventLog;
747 WCHAR szFileName[MAX_PATH];
748
749 ZeroMemory(szFileName, sizeof(szFileName));
750
751 sfn.lpstrFile = szFileName;
752 sfn.nMaxFile = ARRAYSIZE(szFileName);
753
754 if (!GetSaveFileNameW(&sfn))
755 {
756 return;
757 }
758
759 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
760 if (!hEventLog)
761 {
762 ShowLastWin32Error();
763 return;
764 }
765
766 if (!BackupEventLogW(hEventLog, szFileName))
767 {
768 ShowLastWin32Error();
769 }
770
771 CloseEventLog(hEventLog);
772 }
773
774
775 BOOL
776 ClearEvents(VOID)
777 {
778 HANDLE hEventLog;
779 WCHAR szFileName[MAX_PATH];
780 WCHAR szMessage[MAX_LOADSTRING];
781
782 ZeroMemory(szFileName, sizeof(szFileName));
783 ZeroMemory(szMessage, sizeof(szMessage));
784
785 LoadStringW(hInst, IDS_CLEAREVENTS_MSG, szMessage, ARRAYSIZE(szMessage));
786
787 sfn.lpstrFile = szFileName;
788 sfn.nMaxFile = ARRAYSIZE(szFileName);
789
790 switch (MessageBoxW(hwndMainWindow, szMessage, szTitle, MB_YESNOCANCEL | MB_ICONINFORMATION))
791 {
792 case IDCANCEL:
793 {
794 return FALSE;
795 }
796
797 case IDNO:
798 {
799 sfn.lpstrFile = NULL;
800 break;
801 }
802
803 case IDYES:
804 {
805 if (!GetSaveFileNameW(&sfn))
806 {
807 return FALSE;
808 }
809 break;
810 }
811 }
812
813 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
814 if (!hEventLog)
815 {
816 ShowLastWin32Error();
817 return FALSE;
818 }
819
820 if (!ClearEventLogW(hEventLog, sfn.lpstrFile))
821 {
822 ShowLastWin32Error();
823 CloseEventLog(hEventLog);
824 return FALSE;
825 }
826
827 CloseEventLog(hEventLog);
828
829 return TRUE;
830 }
831
832
833 VOID
834 Refresh(VOID)
835 {
836 QueryEventMessages(lpComputerName,
837 lpSourceLogName);
838 }
839
840
841 ATOM
842 MyRegisterClass(HINSTANCE hInstance)
843 {
844 WNDCLASSEXW wcex;
845
846 wcex.cbSize = sizeof(wcex);
847 wcex.style = 0;
848 wcex.lpfnWndProc = WndProc;
849 wcex.cbClsExtra = 0;
850 wcex.cbWndExtra = 0;
851 wcex.hInstance = hInstance;
852 wcex.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_EVENTVWR));
853 wcex.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_ARROW));
854 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
855 wcex.lpszMenuName = MAKEINTRESOURCEW(IDM_EVENTVWR);
856 wcex.lpszClassName = szWindowClass;
857 wcex.hIconSm = (HICON)LoadImageW(hInstance,
858 MAKEINTRESOURCEW(IDI_EVENTVWR),
859 IMAGE_ICON,
860 16,
861 16,
862 LR_SHARED);
863
864 return RegisterClassExW(&wcex);
865 }
866
867
868 VOID
869 GetDisplayNameFile(IN LPCWSTR lpLogName,
870 OUT PWCHAR lpModuleName)
871 {
872 HKEY hKey;
873 WCHAR *KeyPath;
874 WCHAR szModuleName[MAX_PATH];
875 DWORD cbData;
876 SIZE_T cbKeyPath;
877
878 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
879 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
880 if (!KeyPath)
881 {
882 return;
883 }
884
885 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
886 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
887
888 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
889 {
890 HeapFree(GetProcessHeap(), 0, KeyPath);
891 return;
892 }
893
894 cbData = sizeof(szModuleName);
895 if (RegQueryValueExW(hKey, L"DisplayNameFile", NULL, NULL, (LPBYTE)szModuleName, &cbData) == ERROR_SUCCESS)
896 {
897 ExpandEnvironmentStringsW(szModuleName, lpModuleName, MAX_PATH);
898 }
899
900 RegCloseKey(hKey);
901 HeapFree(GetProcessHeap(), 0, KeyPath);
902 }
903
904
905 DWORD
906 GetDisplayNameID(IN LPCWSTR lpLogName)
907 {
908 HKEY hKey;
909 WCHAR *KeyPath;
910 DWORD dwMessageID = 0;
911 DWORD cbData;
912 SIZE_T cbKeyPath;
913
914 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
915 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
916 if (!KeyPath)
917 {
918 return 0;
919 }
920
921 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
922 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
923
924 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
925 {
926 HeapFree(GetProcessHeap(), 0, KeyPath);
927 return 0;
928 }
929
930 cbData = sizeof(dwMessageID);
931 RegQueryValueExW(hKey, L"DisplayNameID", NULL, NULL, (LPBYTE)&dwMessageID, &cbData);
932
933 RegCloseKey(hKey);
934 HeapFree(GetProcessHeap(), 0, KeyPath);
935
936 return dwMessageID;
937 }
938
939
940 VOID
941 BuildLogList(void)
942 {
943 HKEY hKey;
944 DWORD lpcName;
945 DWORD dwIndex;
946 DWORD dwMessageID;
947 DWORD dwMaxKeyLength;
948 WCHAR szModuleName[MAX_PATH];
949 LPWSTR lpDisplayName;
950 HMODULE hLibrary = NULL;
951
952 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, EVENTLOG_BASE_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
953 {
954 return;
955 }
956
957 if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumLogs, &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
958 {
959 RegCloseKey(hKey);
960 return;
961 }
962
963 if (!dwNumLogs)
964 {
965 RegCloseKey(hKey);
966 return;
967 }
968
969 LogNames = HeapAlloc(GetProcessHeap(), 0, (dwNumLogs + 1) * sizeof(LPWSTR));
970
971 if (!LogNames)
972 {
973 RegCloseKey(hKey);
974 return;
975 }
976
977 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
978 {
979 LogNames[dwIndex] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((dwMaxKeyLength + 1) * sizeof(WCHAR)));
980
981 if (LogNames[dwIndex] != NULL)
982 {
983 lpcName = dwMaxKeyLength + 1;
984
985 if (RegEnumKeyExW(hKey, dwIndex, LogNames[dwIndex], &lpcName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
986 {
987 lpDisplayName = NULL;
988
989 ZeroMemory(szModuleName, sizeof(szModuleName));
990 GetDisplayNameFile(LogNames[dwIndex], szModuleName);
991 dwMessageID = GetDisplayNameID(LogNames[dwIndex]);
992
993 hLibrary = LoadLibraryExW(szModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
994 if (hLibrary != NULL)
995 {
996 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
997 hLibrary,
998 dwMessageID,
999 0,
1000 (LPWSTR)&lpDisplayName,
1001 0,
1002 NULL);
1003 FreeLibrary(hLibrary);
1004 }
1005
1006 if (lpDisplayName)
1007 {
1008 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, lpDisplayName);
1009 }
1010 else
1011 {
1012 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, LogNames[dwIndex]);
1013 }
1014
1015 /* Free the buffer allocated by FormatMessage */
1016 if (lpDisplayName)
1017 LocalFree(lpDisplayName);
1018 }
1019 }
1020 }
1021
1022 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_SEPARATOR, ID_FIRST_LOG + dwIndex + 1, NULL);
1023
1024 RegCloseKey(hKey);
1025
1026 return;
1027 }
1028
1029
1030 VOID
1031 FreeLogList(void)
1032 {
1033 DWORD dwIndex;
1034
1035 if (!LogNames)
1036 {
1037 return;
1038 }
1039
1040 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
1041 {
1042 if (LogNames[dwIndex])
1043 {
1044 HeapFree(GetProcessHeap(), 0, LogNames[dwIndex]);
1045 }
1046
1047 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex, MF_BYCOMMAND);
1048 }
1049
1050 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex + 1, MF_BYCOMMAND);
1051
1052 HeapFree(GetProcessHeap(), 0, LogNames);
1053
1054 dwNumLogs = 0;
1055
1056 return;
1057 }
1058
1059
1060 BOOL
1061 InitInstance(HINSTANCE hInstance,
1062 int nCmdShow)
1063 {
1064 HIMAGELIST hSmall;
1065 LVCOLUMNW lvc = {0};
1066 WCHAR szTemp[256];
1067
1068 hInst = hInstance; // Store instance handle in our global variable
1069
1070 hwndMainWindow = CreateWindowW(szWindowClass,
1071 szTitle,
1072 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
1073 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
1074 NULL,
1075 NULL,
1076 hInstance,
1077 NULL);
1078 if (!hwndMainWindow)
1079 {
1080 return FALSE;
1081 }
1082
1083 hwndStatus = CreateWindowExW(0, // no extended styles
1084 STATUSCLASSNAMEW, // status bar
1085 L"", // no text
1086 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
1087 0, 0, 0, 0, // x, y, cx, cy
1088 hwndMainWindow, // parent window
1089 (HMENU)100, // window ID
1090 hInstance, // instance
1091 NULL); // window data
1092
1093 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
1094 // and WS_BORDER to create the normal "sunken" look. Also note that
1095 // LVS_EX_ styles cannot be set in CreateWindowEx().
1096 hwndListView = CreateWindowExW(WS_EX_CLIENTEDGE,
1097 WC_LISTVIEWW,
1098 L"",
1099 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
1100 0,
1101 0,
1102 243,
1103 200,
1104 hwndMainWindow,
1105 NULL,
1106 hInstance,
1107 NULL);
1108
1109 // After the ListView is created, we can add extended list view styles.
1110 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
1111
1112 // Create the ImageList
1113 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1114 GetSystemMetrics(SM_CYSMICON),
1115 ILC_COLOR32,
1116 1,
1117 1);
1118
1119 // Add event type icons to ImageList
1120 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_INFORMATIONICON)));
1121 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_WARNINGICON)));
1122 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ERRORICON)));
1123
1124 // Assign ImageList to List View
1125 (void)ListView_SetImageList(hwndListView, hSmall, LVSIL_SMALL);
1126
1127 // Now set up the listview with its columns.
1128 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
1129 lvc.cx = 90;
1130 LoadStringW(hInstance,
1131 IDS_COLUMNTYPE,
1132 szTemp,
1133 ARRAYSIZE(szTemp));
1134 lvc.pszText = szTemp;
1135 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
1136
1137 lvc.cx = 70;
1138 LoadStringW(hInstance,
1139 IDS_COLUMNDATE,
1140 szTemp,
1141 ARRAYSIZE(szTemp));
1142 lvc.pszText = szTemp;
1143 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
1144
1145 lvc.cx = 70;
1146 LoadStringW(hInstance,
1147 IDS_COLUMNTIME,
1148 szTemp,
1149 ARRAYSIZE(szTemp));
1150 lvc.pszText = szTemp;
1151 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
1152
1153 lvc.cx = 150;
1154 LoadStringW(hInstance,
1155 IDS_COLUMNSOURCE,
1156 szTemp,
1157 ARRAYSIZE(szTemp));
1158 lvc.pszText = szTemp;
1159 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
1160
1161 lvc.cx = 100;
1162 LoadStringW(hInstance,
1163 IDS_COLUMNCATEGORY,
1164 szTemp,
1165 ARRAYSIZE(szTemp));
1166 lvc.pszText = szTemp;
1167 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
1168
1169 lvc.cx = 60;
1170 LoadStringW(hInstance,
1171 IDS_COLUMNEVENT,
1172 szTemp,
1173 ARRAYSIZE(szTemp));
1174 lvc.pszText = szTemp;
1175 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
1176
1177 lvc.cx = 120;
1178 LoadStringW(hInstance,
1179 IDS_COLUMNUSER,
1180 szTemp,
1181 ARRAYSIZE(szTemp));
1182 lvc.pszText = szTemp;
1183 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
1184
1185 lvc.cx = 100;
1186 LoadStringW(hInstance,
1187 IDS_COLUMNCOMPUTER,
1188 szTemp,
1189 ARRAYSIZE(szTemp));
1190 lvc.pszText = szTemp;
1191 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
1192
1193 // Initialize the save Dialog
1194 ZeroMemory(&sfn, sizeof(sfn));
1195 ZeroMemory(szSaveFilter, sizeof(szSaveFilter));
1196
1197 LoadStringW(hInst, IDS_SAVE_FILTER, szSaveFilter, ARRAYSIZE(szSaveFilter));
1198
1199 sfn.lStructSize = sizeof(sfn);
1200 sfn.hwndOwner = hwndMainWindow;
1201 sfn.hInstance = hInstance;
1202 sfn.lpstrFilter = szSaveFilter;
1203 sfn.lpstrInitialDir = NULL;
1204 sfn.Flags = OFN_HIDEREADONLY | OFN_SHAREAWARE;
1205 sfn.lpstrDefExt = NULL;
1206
1207 ShowWindow(hwndMainWindow, nCmdShow);
1208 UpdateWindow(hwndMainWindow);
1209
1210 BuildLogList();
1211
1212 QueryEventMessages(lpComputerName, LogNames[0]);
1213
1214 CheckMenuRadioItem(GetMenu(hwndMainWindow), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, ID_FIRST_LOG, MF_BYCOMMAND);
1215
1216 return TRUE;
1217 }
1218
1219
1220 LRESULT CALLBACK
1221 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1222 {
1223 RECT rect;
1224 NMHDR *hdr;
1225
1226 switch (message)
1227 {
1228 case WM_CREATE:
1229 hMainMenu = GetMenu(hWnd);
1230 break;
1231
1232 case WM_DESTROY:
1233 {
1234 FreeRecords();
1235 FreeLogList();
1236 PostQuitMessage(0);
1237 break;
1238 }
1239
1240 case WM_NOTIFY:
1241 switch (((LPNMHDR)lParam)->code)
1242 {
1243 case NM_DBLCLK:
1244 hdr = (NMHDR FAR*)lParam;
1245 if (hdr->hwndFrom == hwndListView)
1246 {
1247 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
1248
1249 if (lpnmitem->iItem != -1)
1250 {
1251 DialogBoxW(hInst,
1252 MAKEINTRESOURCEW(IDD_EVENTPROPERTIES),
1253 hWnd,
1254 EventDetails);
1255 }
1256 }
1257 break;
1258 }
1259 break;
1260
1261 case WM_COMMAND:
1262 {
1263 // Parse the menu selections:
1264
1265 if ((LOWORD(wParam) >= ID_FIRST_LOG) && (LOWORD(wParam) <= ID_FIRST_LOG + dwNumLogs))
1266 {
1267 if (LogNames[LOWORD(wParam) - ID_FIRST_LOG])
1268 {
1269 if (QueryEventMessages(lpComputerName, LogNames[LOWORD(wParam) - ID_FIRST_LOG]))
1270 {
1271 CheckMenuRadioItem(GetMenu(hWnd), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, LOWORD(wParam), MF_BYCOMMAND);
1272 }
1273 }
1274 }
1275 else
1276
1277 switch (LOWORD(wParam))
1278 {
1279 case IDM_SAVE_PROTOCOL:
1280 SaveProtocol();
1281 break;
1282
1283 case IDM_CLEAR_EVENTS:
1284 if (ClearEvents())
1285 {
1286 Refresh();
1287 }
1288 break;
1289
1290 case IDM_REFRESH:
1291 Refresh();
1292 break;
1293
1294 case IDM_ABOUT:
1295 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_ABOUTBOX), hWnd, About);
1296 break;
1297
1298 case IDM_HELP:
1299 MessageBoxW(hwndMainWindow,
1300 L"Help not implemented yet!",
1301 L"Event Log",
1302 MB_OK | MB_ICONINFORMATION);
1303 break;
1304
1305 case IDM_EXIT:
1306 DestroyWindow(hWnd);
1307 break;
1308
1309 default:
1310 return DefWindowProcW(hWnd, message, wParam, lParam);
1311 }
1312 break;
1313 }
1314
1315 case WM_SIZE:
1316 {
1317 // Gets the window rectangle
1318 GetClientRect(hWnd, &rect);
1319
1320 // Relocate the listview
1321 MoveWindow(hwndListView,
1322 0,
1323 0,
1324 rect.right,
1325 rect.bottom - 20,
1326 1);
1327
1328 // Resize the statusbar;
1329 SendMessageW(hwndStatus, message, wParam, lParam);
1330 break;
1331 }
1332
1333 default:
1334 return DefWindowProcW(hWnd, message, wParam, lParam);
1335 }
1336
1337 return 0;
1338 }
1339
1340
1341 // Message handler for about box.
1342 INT_PTR CALLBACK
1343 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1344 {
1345 UNREFERENCED_PARAMETER(lParam);
1346 switch (message)
1347 {
1348 case WM_INITDIALOG:
1349 {
1350 return (INT_PTR)TRUE;
1351 }
1352
1353 case WM_COMMAND:
1354 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1355 {
1356 EndDialog(hDlg, LOWORD(wParam));
1357 return (INT_PTR)TRUE;
1358 }
1359 break;
1360 }
1361
1362 return (INT_PTR)FALSE;
1363 }
1364
1365 VOID
1366 DisplayEvent(HWND hDlg)
1367 {
1368 WCHAR szEventType[MAX_PATH];
1369 WCHAR szTime[MAX_PATH];
1370 WCHAR szDate[MAX_PATH];
1371 WCHAR szUser[MAX_PATH];
1372 WCHAR szComputer[MAX_PATH];
1373 WCHAR szSource[MAX_PATH];
1374 WCHAR szCategory[MAX_PATH];
1375 WCHAR szEventID[MAX_PATH];
1376 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1377 BOOL bEventData = FALSE;
1378 LVITEMW li;
1379 EVENTLOGRECORD* pevlr;
1380 int iIndex;
1381
1382 // Get index of selected item
1383 iIndex = (int)SendMessageW(hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1384 if (iIndex == -1)
1385 {
1386 MessageBoxW(NULL,
1387 L"No Items in ListView",
1388 L"Error",
1389 MB_OK | MB_ICONINFORMATION);
1390 return;
1391 }
1392
1393 li.mask = LVIF_PARAM;
1394 li.iItem = iIndex;
1395 li.iSubItem = 0;
1396
1397 (void)ListView_GetItem(hwndListView, &li);
1398
1399 pevlr = (EVENTLOGRECORD*)li.lParam;
1400
1401 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, ARRAYSIZE(szEventType));
1402 ListView_GetItemText(hwndListView, iIndex, 1, szDate, ARRAYSIZE(szDate));
1403 ListView_GetItemText(hwndListView, iIndex, 2, szTime, ARRAYSIZE(szTime));
1404 ListView_GetItemText(hwndListView, iIndex, 3, szSource, ARRAYSIZE(szSource));
1405 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, ARRAYSIZE(szCategory));
1406 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, ARRAYSIZE(szEventID));
1407 ListView_GetItemText(hwndListView, iIndex, 6, szUser, ARRAYSIZE(szUser));
1408 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, ARRAYSIZE(szComputer));
1409
1410 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
1411 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
1412 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
1413 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1414 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1415 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1416 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
1417 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1418
1419 bEventData = (pevlr->DataLength > 0);
1420 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1421 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1422
1423 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1424 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1425 }
1426
1427 UINT
1428 PrintByteDataLine(PWCHAR pBuffer, UINT uOffset, PBYTE pd, UINT uLength)
1429 {
1430 PWCHAR p = pBuffer;
1431 UINT n, i, r = 0;
1432
1433 if (uOffset != 0)
1434 {
1435 n = swprintf(p, L"\r\n");
1436 p = p + n;
1437 r += n;
1438 }
1439
1440 n = swprintf(p, L"%04lx:", uOffset);
1441 p = p + n;
1442 r += n;
1443
1444 for (i = 0; i < uLength; i++)
1445 {
1446 n = swprintf(p, L" %02x", pd[i]);
1447 p = p + n;
1448 r += n;
1449 }
1450
1451 for (i = 0; i < 9 - uLength; i++)
1452 {
1453 n = swprintf(p, L" ");
1454 p = p + n;
1455 r += n;
1456 }
1457
1458 for (i = 0; i < uLength; i++)
1459 {
1460 n = swprintf(p, L"%c", iswprint(pd[i]) ? pd[i] : L'.');
1461 p = p + n;
1462 r += n;
1463 }
1464
1465 return r;
1466 }
1467
1468 UINT
1469 PrintWordDataLine(PWCHAR pBuffer, UINT uOffset, PULONG pData, UINT uLength)
1470 {
1471 PWCHAR p = pBuffer;
1472 UINT n, i, r = 0;
1473
1474 if (uOffset != 0)
1475 {
1476 n = swprintf(p, L"\r\n");
1477 p = p + n;
1478 r += n;
1479 }
1480
1481 n = swprintf(p, L"%04lx:", uOffset);
1482 p = p + n;
1483 r += n;
1484
1485 for (i = 0; i < uLength / sizeof(ULONG); i++)
1486 {
1487 n = swprintf(p, L" %08lx", pData[i]);
1488 p = p + n;
1489 r += n;
1490 }
1491
1492 return r;
1493 }
1494
1495
1496 VOID
1497 DisplayEventData(HWND hDlg, BOOL bDisplayWords)
1498 {
1499 LVITEMW li;
1500 EVENTLOGRECORD* pevlr;
1501 int iIndex;
1502
1503 LPBYTE pData;
1504 UINT i, uOffset;
1505 UINT uBufferSize, uLineLength;
1506 PWCHAR pTextBuffer, pLine;
1507
1508 // Get index of selected item
1509 iIndex = (int)SendMessageW(hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1510 if (iIndex == -1)
1511 {
1512 MessageBoxW(NULL,
1513 L"No Items in ListView",
1514 L"Error",
1515 MB_OK | MB_ICONINFORMATION);
1516 return;
1517 }
1518
1519 li.mask = LVIF_PARAM;
1520 li.iItem = iIndex;
1521 li.iSubItem = 0;
1522
1523 (void)ListView_GetItem(hwndListView, &li);
1524
1525 pevlr = (EVENTLOGRECORD*)li.lParam;
1526 if (pevlr->DataLength == 0)
1527 {
1528 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L"");
1529 return;
1530 }
1531
1532 if (bDisplayWords)
1533 uBufferSize = ((pevlr->DataLength / 8) + 1) * 26 * sizeof(WCHAR);
1534 else
1535 uBufferSize = ((pevlr->DataLength / 8) + 1) * 43 * sizeof(WCHAR);
1536
1537 pTextBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uBufferSize);
1538 if (pTextBuffer)
1539 {
1540 pLine = pTextBuffer;
1541 uOffset = 0;
1542
1543 for (i = 0; i < pevlr->DataLength / 8; i++)
1544 {
1545 pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset);
1546
1547 if (bDisplayWords)
1548 uLineLength = PrintWordDataLine(pLine, uOffset, (PULONG)pData, 8);
1549 else
1550 uLineLength = PrintByteDataLine(pLine, uOffset, pData, 8);
1551 pLine = pLine + uLineLength;
1552
1553 uOffset += 8;
1554 }
1555
1556 if (pevlr->DataLength % 8 != 0)
1557 {
1558 pData = (LPBYTE)((LPBYTE)pevlr + pevlr->DataOffset + uOffset);
1559
1560 if (bDisplayWords)
1561 PrintWordDataLine(pLine, uOffset, (PULONG)pData, pevlr->DataLength % 8);
1562 else
1563 PrintByteDataLine(pLine, uOffset, pData, pevlr->DataLength % 8);
1564 }
1565
1566 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, pTextBuffer);
1567
1568 HeapFree(GetProcessHeap(), 0, pTextBuffer);
1569 }
1570 }
1571
1572 HFONT
1573 CreateMonospaceFont(VOID)
1574 {
1575 LOGFONTW tmpFont = {0};
1576 HFONT hFont;
1577 HDC hDc;
1578
1579 hDc = GetDC(NULL);
1580
1581 tmpFont.lfHeight = -MulDiv(8, GetDeviceCaps(hDc, LOGPIXELSY), 72);
1582 tmpFont.lfWeight = FW_NORMAL;
1583 wcscpy(tmpFont.lfFaceName, L"Courier");
1584
1585 hFont = CreateFontIndirectW(&tmpFont);
1586
1587 ReleaseDC(NULL, hDc);
1588
1589 return hFont;
1590 }
1591
1592 VOID
1593 CopyEventEntry(HWND hWnd)
1594 {
1595 WCHAR output[4130], tmpHeader[512];
1596 WCHAR szEventType[MAX_PATH];
1597 WCHAR szSource[MAX_PATH];
1598 WCHAR szCategory[MAX_PATH];
1599 WCHAR szEventID[MAX_PATH];
1600 WCHAR szDate[MAX_PATH];
1601 WCHAR szTime[MAX_PATH];
1602 WCHAR szUser[MAX_PATH];
1603 WCHAR szComputer[MAX_PATH];
1604 WCHAR evtDesc[ENTRY_SIZE];
1605 HGLOBAL hMem;
1606
1607 if (!OpenClipboard(hWnd))
1608 return;
1609
1610 /* First, empty the clipboard before we begin to use it */
1611 EmptyClipboard();
1612
1613 /* Get the formatted text needed to place the content into */
1614 LoadStringW(hInst, IDS_COPY, tmpHeader, ARRAYSIZE(tmpHeader));
1615
1616 /* Grabs all the information and get it ready for the clipboard */
1617 GetDlgItemTextW(hWnd, IDC_EVENTTYPESTATIC, szEventType, ARRAYSIZE(szEventType));
1618 GetDlgItemTextW(hWnd, IDC_EVENTSOURCESTATIC, szSource, ARRAYSIZE(szSource));
1619 GetDlgItemTextW(hWnd, IDC_EVENTCATEGORYSTATIC, szCategory, ARRAYSIZE(szCategory));
1620 GetDlgItemTextW(hWnd, IDC_EVENTIDSTATIC, szEventID, ARRAYSIZE(szEventID));
1621 GetDlgItemTextW(hWnd, IDC_EVENTDATESTATIC, szDate, ARRAYSIZE(szDate));
1622 GetDlgItemTextW(hWnd, IDC_EVENTTIMESTATIC, szTime, ARRAYSIZE(szTime));
1623 GetDlgItemTextW(hWnd, IDC_EVENTUSERSTATIC, szUser, ARRAYSIZE(szUser));
1624 GetDlgItemTextW(hWnd, IDC_EVENTCOMPUTERSTATIC, szComputer, ARRAYSIZE(szComputer));
1625 GetDlgItemTextW(hWnd, IDC_EVENTTEXTEDIT, evtDesc, ARRAYSIZE(evtDesc));
1626
1627 /* Consolidate the information into on big piece */
1628 wsprintfW(output, tmpHeader, szEventType, szSource, szCategory, szEventID, szDate, szTime, szUser, szComputer, evtDesc);
1629
1630 /* Sort out the memory needed to write to the clipboard */
1631 hMem = GlobalAlloc(GMEM_MOVEABLE, ENTRY_SIZE);
1632 memcpy(GlobalLock(hMem), output, ENTRY_SIZE);
1633 GlobalUnlock(hMem);
1634
1635 /* Write the final content to the clipboard */
1636 SetClipboardData(CF_UNICODETEXT, hMem);
1637
1638 /* Close the clipboard once we're done with it */
1639 CloseClipboard();
1640 }
1641
1642 static
1643 INT_PTR CALLBACK
1644 StatusMessageWindowProc(IN HWND hwndDlg,
1645 IN UINT uMsg,
1646 IN WPARAM wParam,
1647 IN LPARAM lParam)
1648 {
1649 UNREFERENCED_PARAMETER(hwndDlg);
1650 UNREFERENCED_PARAMETER(wParam);
1651 UNREFERENCED_PARAMETER(lParam);
1652
1653 switch (uMsg)
1654 {
1655 case WM_INITDIALOG:
1656 return TRUE;
1657 }
1658 return FALSE;
1659 }
1660
1661 static
1662 VOID
1663 InitDetailsDlg(HWND hDlg, PDETAILDATA pData)
1664 {
1665 HANDLE nextIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_NEXT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1666 HANDLE prevIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_PREV), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1667 HANDLE copyIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_COPY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1668
1669 SendMessageW(GetDlgItem(hDlg, IDC_NEXT), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)nextIcon);
1670 SendMessageW(GetDlgItem(hDlg, IDC_PREVIOUS), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)prevIcon);
1671 SendMessageW(GetDlgItem(hDlg, IDC_COPY), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)copyIcon);
1672
1673 SendDlgItemMessageW(hDlg, pData->bDisplayWords ? IDC_WORDRADIO : IDC_BYTESRADIO, BM_SETCHECK, BST_CHECKED, 0);
1674 SendDlgItemMessageW(hDlg, IDC_EVENTDATAEDIT, WM_SETFONT, (WPARAM)pData->hMonospaceFont, (LPARAM)TRUE);
1675 }
1676
1677 // Message handler for event details box.
1678 INT_PTR CALLBACK
1679 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1680 {
1681 PDETAILDATA pData;
1682
1683 UNREFERENCED_PARAMETER(lParam);
1684
1685 pData = (PDETAILDATA)GetWindowLongPtr(hDlg, DWLP_USER);
1686
1687 switch (message)
1688 {
1689 case WM_INITDIALOG:
1690 pData = (PDETAILDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DETAILDATA));
1691 if (pData)
1692 {
1693 SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pData);
1694
1695 pData->bDisplayWords = FALSE;
1696 pData->hMonospaceFont = CreateMonospaceFont();
1697
1698 InitDetailsDlg(hDlg, pData);
1699
1700 // Show event info on dialog box
1701 DisplayEvent(hDlg);
1702 DisplayEventData(hDlg, pData->bDisplayWords);
1703 }
1704 return (INT_PTR)TRUE;
1705
1706 case WM_DESTROY:
1707 if (pData->hMonospaceFont)
1708 DeleteObject(pData->hMonospaceFont);
1709 HeapFree(GetProcessHeap(), 0, pData);
1710 return (INT_PTR)TRUE;
1711
1712 case WM_COMMAND:
1713 switch (LOWORD(wParam))
1714 {
1715 case IDOK:
1716 case IDCANCEL:
1717 EndDialog(hDlg, LOWORD(wParam));
1718 return (INT_PTR)TRUE;
1719
1720 case IDC_PREVIOUS:
1721 SendMessageW(hwndListView, WM_KEYDOWN, VK_UP, 0);
1722
1723 // Show event info on dialog box
1724 if (pData)
1725 {
1726 DisplayEvent(hDlg);
1727 DisplayEventData(hDlg, pData->bDisplayWords);
1728 }
1729 return (INT_PTR)TRUE;
1730
1731 case IDC_NEXT:
1732 SendMessageW(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1733
1734 // Show event info on dialog box
1735 if (pData)
1736 {
1737 DisplayEvent(hDlg);
1738 DisplayEventData(hDlg, pData->bDisplayWords);
1739 }
1740 return (INT_PTR)TRUE;
1741
1742 case IDC_COPY:
1743 CopyEventEntry(hDlg);
1744 return (INT_PTR)TRUE;
1745
1746 case IDC_BYTESRADIO:
1747 if (pData)
1748 {
1749 pData->bDisplayWords = FALSE;
1750 DisplayEventData(hDlg, pData->bDisplayWords);
1751 }
1752 return (INT_PTR)TRUE;
1753
1754 case IDC_WORDRADIO:
1755 if (pData)
1756 {
1757 pData->bDisplayWords = TRUE;
1758 DisplayEventData(hDlg, pData->bDisplayWords);
1759 }
1760 return (INT_PTR)TRUE;
1761
1762 case IDHELP:
1763 MessageBoxW(hDlg,
1764 L"Help not implemented yet!",
1765 L"Event Log",
1766 MB_OK | MB_ICONINFORMATION);
1767 return (INT_PTR)TRUE;
1768
1769 default:
1770 break;
1771 }
1772 break;
1773 }
1774
1775 return (INT_PTR)FALSE;
1776 }