* Sync with trunk r64401.
[reactos.git] / 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 <windef.h>
29 #include <winbase.h>
30 #include <winuser.h>
31 #include <wingdi.h>
32 #include <winnls.h>
33 #include <winreg.h>
34 #include <commctrl.h>
35 #include <commdlg.h>
36 #include <strsafe.h>
37
38 #include "resource.h"
39
40 #if _MSC_VER
41 #pragma warning(disable: 4996) /* 'strdup' was declared deprecated */
42 #define _CRT_SECURE_NO_DEPRECATE /* all deprecated unsafe string functions */
43 #endif
44
45 static const WCHAR szWindowClass[] = L"EVENTVWR"; /* the main window class name*/
46 static const WCHAR EVENTLOG_BASE_KEY[] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
47
48 // MessageFile message buffer size
49 #define EVENT_MESSAGE_EVENTTEXT_BUFFER 1024*10
50 #define EVENT_MESSAGE_FILE_BUFFER 1024*10
51 #define EVENT_DLL_SEPARATOR L";"
52 #define EVENT_MESSAGE_FILE L"EventMessageFile"
53 #define EVENT_CATEGORY_MESSAGE_FILE L"CategoryMessageFile"
54 #define EVENT_PARAMETER_MESSAGE_FILE L"ParameterMessageFile"
55
56 #define MAX_LOADSTRING 255
57
58 /* Globals */
59 HINSTANCE hInst; /* current instance */
60 WCHAR szTitle[MAX_LOADSTRING]; /* The title bar text */
61 WCHAR szTitleTemplate[MAX_LOADSTRING]; /* The logged-on title bar text */
62 WCHAR szSaveFilter[MAX_LOADSTRING]; /* Filter Mask for the save Dialog */
63 HWND hwndMainWindow; /* Main window */
64 HWND hwndListView; /* ListView control */
65 HWND hwndStatus; /* Status bar */
66 HMENU hMainMenu; /* The application's main menu */
67 WCHAR szStatusBarTemplate[MAX_LOADSTRING]; /* The status bar text */
68 PEVENTLOGRECORD *g_RecordPtrs = NULL;
69 DWORD g_TotalRecords = 0;
70 OPENFILENAMEW sfn;
71
72 LPWSTR lpSourceLogName = NULL;
73 LPWSTR lpComputerName = NULL;
74
75 DWORD dwNumLogs = 0;
76 WCHAR **LogNames;
77
78 /* Forward declarations of functions included in this code module: */
79 ATOM MyRegisterClass(HINSTANCE hInstance);
80 BOOL InitInstance(HINSTANCE, int);
81 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
82 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
83 INT_PTR CALLBACK EventDetails(HWND, UINT, WPARAM, LPARAM);
84 static INT_PTR CALLBACK StatusMessageWindowProc (HWND, UINT, WPARAM, LPARAM);
85
86
87 int APIENTRY
88 wWinMain(HINSTANCE hInstance,
89 HINSTANCE hPrevInstance,
90 LPWSTR lpCmdLine,
91 int nCmdShow)
92 {
93 MSG msg;
94 HACCEL hAccelTable;
95 INITCOMMONCONTROLSEX iccx;
96
97 UNREFERENCED_PARAMETER(hPrevInstance);
98 UNREFERENCED_PARAMETER(lpCmdLine);
99
100 /* Whenever any of the common controls are used in your app,
101 * you must call InitCommonControlsEx() to register the classes
102 * for those controls. */
103 iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
104 iccx.dwICC = ICC_LISTVIEW_CLASSES;
105 InitCommonControlsEx(&iccx);
106
107 /* Initialize global strings */
108 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
109 LoadStringW(hInstance, IDS_APP_TITLE_EX, szTitleTemplate, MAX_LOADSTRING);
110 LoadStringW(hInstance, IDS_STATUS_MSG, szStatusBarTemplate, MAX_LOADSTRING);
111 MyRegisterClass(hInstance);
112
113 /* Perform application initialization: */
114 if (!InitInstance(hInstance, nCmdShow))
115 {
116 return FALSE;
117 }
118
119 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EVENTVWR));
120
121 /* Main message loop: */
122 while (GetMessageW(&msg, NULL, 0, 0))
123 {
124 if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg))
125 {
126 TranslateMessage(&msg);
127 DispatchMessage(&msg);
128 }
129 }
130
131 return (int)msg.wParam;
132 }
133
134 static void FreeRecords(void)
135 {
136 DWORD iIndex;
137
138 if (!g_RecordPtrs)
139 return;
140
141 for (iIndex = 0; iIndex < g_TotalRecords; iIndex++)
142 HeapFree(GetProcessHeap(), 0, g_RecordPtrs[iIndex]);
143 HeapFree(GetProcessHeap(), 0, g_RecordPtrs);
144 g_RecordPtrs = NULL;
145 }
146
147 VOID
148 ShowLastWin32Error(VOID)
149 {
150 DWORD dwError;
151 LPWSTR lpMessageBuffer;
152
153 dwError = GetLastError();
154 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
155 NULL,
156 dwError,
157 0,
158 (LPWSTR)&lpMessageBuffer,
159 0,
160 NULL);
161
162 MessageBoxW(hwndMainWindow, lpMessageBuffer, szTitle, MB_OK | MB_ICONERROR);
163 LocalFree(lpMessageBuffer);
164 }
165
166 VOID
167 EventTimeToSystemTime(DWORD EventTime,
168 SYSTEMTIME *pSystemTime)
169 {
170 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
171 FILETIME ftLocal;
172 union
173 {
174 FILETIME ft;
175 ULONGLONG ll;
176 } u1970, uUCT;
177
178 uUCT.ft.dwHighDateTime = 0;
179 uUCT.ft.dwLowDateTime = EventTime;
180 SystemTimeToFileTime(&st1970, &u1970.ft);
181 uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
182 FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
183 FileTimeToSystemTime(&ftLocal, pSystemTime);
184 }
185
186
187 void
188 TrimNulls(LPWSTR s)
189 {
190 WCHAR *c;
191
192 if (s != NULL)
193 {
194 c = s + wcslen(s) - 1;
195 while (c >= s && iswspace(*c))
196 --c;
197 *++c = L'\0';
198 }
199 }
200
201
202 BOOL
203 GetEventMessageFileDLL(IN LPCWSTR lpLogName,
204 IN LPCWSTR SourceName,
205 IN LPCWSTR EntryName,
206 OUT PWCHAR ExpandedName)
207 {
208 DWORD dwSize;
209 BYTE szModuleName[MAX_PATH];
210 WCHAR szKeyName[MAX_PATH];
211 HKEY hAppKey = NULL;
212 HKEY hSourceKey = NULL;
213 BOOL bReturn = FALSE;
214
215 StringCbCopyW(szKeyName, sizeof(szKeyName), L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\");
216 StringCbCatW(szKeyName, sizeof(szKeyName), lpLogName);
217
218 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
219 szKeyName,
220 0,
221 KEY_READ,
222 &hAppKey) == ERROR_SUCCESS)
223 {
224 if (RegOpenKeyExW(hAppKey,
225 SourceName,
226 0,
227 KEY_READ,
228 &hSourceKey) == ERROR_SUCCESS)
229 {
230 dwSize = MAX_PATH;
231 if (RegQueryValueExW(hSourceKey,
232 EntryName,
233 NULL,
234 NULL,
235 (LPBYTE)szModuleName,
236 &dwSize) == ERROR_SUCCESS)
237 {
238 /* Returns a string containing the requested substituted environment variable. */
239 ExpandEnvironmentStringsW((LPCWSTR)szModuleName, ExpandedName, MAX_PATH);
240
241 /* Successful */
242 bReturn = TRUE;
243 }
244 }
245 }
246 else
247 {
248 ShowLastWin32Error();
249 }
250
251 if (hSourceKey != NULL)
252 RegCloseKey(hSourceKey);
253
254 if (hAppKey != NULL)
255 RegCloseKey(hAppKey);
256
257 return bReturn;
258 }
259
260
261 BOOL
262 GetEventCategory(IN LPCWSTR KeyName,
263 IN LPCWSTR SourceName,
264 IN EVENTLOGRECORD *pevlr,
265 OUT PWCHAR CategoryName)
266 {
267 HANDLE hLibrary = NULL;
268 WCHAR szMessageDLL[MAX_PATH];
269 LPVOID lpMsgBuf = NULL;
270
271 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_CATEGORY_MESSAGE_FILE , szMessageDLL))
272 {
273 hLibrary = LoadLibraryExW(szMessageDLL,
274 NULL,
275 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
276 if (hLibrary != NULL)
277 {
278 /* Retrieve the message string. */
279 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
280 hLibrary,
281 pevlr->EventCategory,
282 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
283 (LPWSTR)&lpMsgBuf,
284 EVENT_MESSAGE_FILE_BUFFER,
285 NULL) != 0)
286 {
287 /* Trim the string */
288 TrimNulls(lpMsgBuf);
289
290 /* Copy the category name */
291 StringCchCopyW(CategoryName, MAX_PATH, lpMsgBuf);
292 }
293 else
294 {
295 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
296 }
297
298 if (hLibrary != NULL)
299 FreeLibrary(hLibrary);
300
301 /* Free the buffer allocated by FormatMessage */
302 if (lpMsgBuf)
303 LocalFree(lpMsgBuf);
304
305 return TRUE;
306 }
307 }
308
309 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
310
311 return FALSE;
312 }
313
314
315 BOOL
316 GetEventMessage(IN LPCWSTR KeyName,
317 IN LPCWSTR SourceName,
318 IN EVENTLOGRECORD *pevlr,
319 OUT PWCHAR EventText)
320 {
321 DWORD i;
322 HANDLE hLibrary = NULL;
323 WCHAR SourceModuleName[1000];
324 WCHAR ParameterModuleName[1000];
325 LPWSTR lpMsgBuf = NULL;
326 WCHAR szStringIDNotFound[MAX_LOADSTRING];
327 LPWSTR szDll;
328 LPWSTR szMessage;
329 LPWSTR *szArguments;
330 BOOL bDone = FALSE;
331
332 /* TODO : GetEventMessageFileDLL can return a comma separated list of DLLs */
333 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_MESSAGE_FILE, SourceModuleName))
334 {
335 /* Get the event message */
336 szMessage = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
337
338 /* Allocate space for parameters */
339 szArguments = malloc(sizeof(LPVOID) * pevlr->NumStrings);
340 if (!szArguments)
341 {
342 return FALSE;
343 }
344
345 for (i = 0; i < pevlr->NumStrings ; i++)
346 {
347 if (wcsstr(szMessage , L"%%"))
348 {
349 if (GetEventMessageFileDLL(KeyName, SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
350 {
351 /* Not yet support for reading messages from parameter message DLL */
352 }
353 }
354
355 szArguments[i] = szMessage;
356 szMessage += wcslen(szMessage) + 1;
357 }
358
359 szDll = wcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
360 while ((szDll != NULL) && (!bDone))
361 {
362 hLibrary = LoadLibraryExW(szDll,
363 NULL,
364 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
365 if (hLibrary == NULL)
366 {
367 /* The DLL could not be loaded try the next one (if any) */
368 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
369 }
370 else
371 {
372 /* Retrieve the message string. */
373 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
374 FORMAT_MESSAGE_ALLOCATE_BUFFER |
375 FORMAT_MESSAGE_FROM_HMODULE |
376 FORMAT_MESSAGE_ARGUMENT_ARRAY,
377 hLibrary,
378 pevlr->EventID,
379 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
380 (LPWSTR)&lpMsgBuf,
381 0,
382 (va_list*)szArguments) == 0)
383 {
384 /* We haven't found the string , get next DLL (if any) */
385 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
386 }
387 else
388 {
389 if (lpMsgBuf)
390 {
391 /* The ID was found and the message was formated */
392 bDone = TRUE;
393
394 /* Trim the string */
395 TrimNulls((LPWSTR)lpMsgBuf);
396
397 /* Copy the event text */
398 StringCchCopyW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, lpMsgBuf);
399 }
400 }
401
402 FreeLibrary(hLibrary);
403 }
404 }
405
406 if (!bDone)
407 {
408 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
409 StringCchPrintfW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
410 }
411
412 free(szArguments);
413
414 /* No more dlls to try, return result */
415 return bDone;
416 }
417
418 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
419 StringCchPrintfW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
420
421 return FALSE;
422 }
423
424
425 VOID
426 GetEventType(IN WORD dwEventType,
427 OUT PWCHAR eventTypeText)
428 {
429 switch (dwEventType)
430 {
431 case EVENTLOG_ERROR_TYPE:
432 LoadStringW(hInst, IDS_EVENTLOG_ERROR_TYPE, eventTypeText, MAX_LOADSTRING);
433 break;
434 case EVENTLOG_WARNING_TYPE:
435 LoadStringW(hInst, IDS_EVENTLOG_WARNING_TYPE, eventTypeText, MAX_LOADSTRING);
436 break;
437 case EVENTLOG_INFORMATION_TYPE:
438 LoadStringW(hInst, IDS_EVENTLOG_INFORMATION_TYPE, eventTypeText, MAX_LOADSTRING);
439 break;
440 case EVENTLOG_AUDIT_SUCCESS:
441 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_SUCCESS, eventTypeText, MAX_LOADSTRING);
442 break;
443 case EVENTLOG_AUDIT_FAILURE:
444 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_FAILURE, eventTypeText, MAX_LOADSTRING);
445 break;
446 case EVENTLOG_SUCCESS:
447 LoadStringW(hInst, IDS_EVENTLOG_SUCCESS, eventTypeText, MAX_LOADSTRING);
448 break;
449 default:
450 LoadStringW(hInst, IDS_EVENTLOG_UNKNOWN_TYPE, eventTypeText, MAX_LOADSTRING);
451 break;
452 }
453 }
454
455 BOOL
456 GetEventUserName(EVENTLOGRECORD *pelr,
457 OUT PWCHAR pszUser)
458 {
459 PSID lpSid;
460 WCHAR szName[1024];
461 WCHAR szDomain[1024];
462 SID_NAME_USE peUse;
463 DWORD cbName = 1024;
464 DWORD cbDomain = 1024;
465
466 /* Point to the SID. */
467 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
468
469 /* User SID */
470 if (pelr->UserSidLength > 0)
471 {
472 if (LookupAccountSidW(NULL,
473 lpSid,
474 szName,
475 &cbName,
476 szDomain,
477 &cbDomain,
478 &peUse))
479 {
480 StringCchCopyW(pszUser, MAX_PATH, szName);
481 return TRUE;
482 }
483 }
484
485 return FALSE;
486 }
487
488
489 static DWORD WINAPI
490 ShowStatusMessageThread(IN LPVOID lpParameter)
491 {
492 HWND *phWnd = (HWND *)lpParameter;
493 HWND hWnd;
494 MSG Msg;
495
496 hWnd = CreateDialogParam(hInst,
497 MAKEINTRESOURCE(IDD_PROGRESSBOX),
498 GetDesktopWindow(),
499 StatusMessageWindowProc,
500 (LPARAM)NULL);
501 if (!hWnd)
502 return 0;
503
504 *phWnd = hWnd;
505
506 ShowWindow(hWnd, SW_SHOW);
507
508 /* Message loop for the Status window */
509 while (GetMessage(&Msg, NULL, 0, 0))
510 {
511 TranslateMessage(&Msg);
512 DispatchMessage(&Msg);
513 }
514
515 return 0;
516 }
517
518
519 BOOL
520 QueryEventMessages(LPWSTR lpMachineName,
521 LPWSTR lpLogName)
522 {
523 HWND hwndDlg;
524 HANDLE hEventLog;
525 EVENTLOGRECORD *pevlr;
526 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords = 0, dwCurrentRecord = 0, dwRecordsToRead = 0, dwFlags, dwMaxLength;
527 size_t cchRemaining;
528 LPWSTR lpSourceName;
529 LPWSTR lpComputerName;
530 LPSTR lpData;
531 BOOL bResult = TRUE; /* Read succeeded. */
532
533 WCHAR szWindowTitle[MAX_PATH];
534 WCHAR szStatusText[MAX_PATH];
535 WCHAR szLocalDate[MAX_PATH];
536 WCHAR szLocalTime[MAX_PATH];
537 WCHAR szEventID[MAX_PATH];
538 WCHAR szEventTypeText[MAX_LOADSTRING];
539 WCHAR szCategoryID[MAX_PATH];
540 WCHAR szUsername[MAX_PATH];
541 WCHAR szEventText[EVENT_MESSAGE_FILE_BUFFER];
542 WCHAR szCategory[MAX_PATH];
543 WCHAR szData[MAX_PATH];
544 PWCHAR lpTitleTemplateEnd;
545
546 SYSTEMTIME time;
547 LVITEMW lviEventItem;
548
549 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
550
551 /* Open the event log. */
552 hEventLog = OpenEventLogW(lpMachineName,
553 lpLogName);
554 if (hEventLog == NULL)
555 {
556 ShowLastWin32Error();
557 return FALSE;
558 }
559
560 lpSourceLogName = lpLogName;
561 lpComputerName = lpMachineName;
562
563 /* Disable listview redraw */
564 SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0);
565
566 /* Clear the list view */
567 (void)ListView_DeleteAllItems (hwndListView);
568 FreeRecords();
569
570 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
571
572 /* Get the total number of event log records. */
573 GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords);
574 g_TotalRecords = dwTotalRecords;
575
576 if (dwTotalRecords > 0)
577 {
578 EnableMenuItem(hMainMenu, ID_CLEAR_EVENTS, MF_BYCOMMAND | MF_ENABLED);
579 EnableMenuItem(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_ENABLED);
580 }
581 else
582 {
583 EnableMenuItem(hMainMenu, ID_CLEAR_EVENTS, MF_BYCOMMAND | MF_GRAYED);
584 EnableMenuItem(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_GRAYED);
585 }
586
587 g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(PVOID));
588
589 /* If we have at least 1000 records show the waiting dialog */
590 if (dwTotalRecords > 1000)
591 {
592 CloseHandle(CreateThread(NULL,
593 0,
594 ShowStatusMessageThread,
595 (LPVOID)&hwndDlg,
596 0,
597 NULL));
598 }
599
600 while (dwCurrentRecord < dwTotalRecords)
601 {
602 pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD) * dwTotalRecords);
603 g_RecordPtrs[dwCurrentRecord] = pevlr;
604
605 bResult = ReadEventLog(hEventLog, // Event log handle
606 dwFlags, // Sequential read
607 0, // Ignored for sequential read
608 pevlr, // Pointer to buffer
609 sizeof(EVENTLOGRECORD), // Size of buffer
610 &dwRead, // Number of bytes read
611 &dwNeeded); // Bytes in the next record
612 if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
613 {
614 HeapFree(GetProcessHeap(), 0, pevlr);
615 pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded);
616 g_RecordPtrs[dwCurrentRecord] = pevlr;
617
618 ReadEventLogW(hEventLog, // event log handle
619 dwFlags, // read flags
620 0, // offset; default is 0
621 pevlr, // pointer to buffer
622 dwNeeded, // size of buffer
623 &dwRead, // number of bytes read
624 &dwNeeded); // bytes in next record
625 }
626
627 while (dwRead > 0)
628 {
629 LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, MAX_PATH);
630 LoadStringW(hInst, IDS_NOT_AVAILABLE, szEventText, MAX_PATH);
631 LoadStringW(hInst, IDS_NONE, szCategory, MAX_PATH);
632
633 // Get the event source name.
634 lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
635
636 // Get the computer name
637 lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR));
638
639 // This ist the data section of the current event
640 lpData = (LPSTR)((LPBYTE)pevlr + pevlr->DataOffset);
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, MAX_PATH);
649 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, szLocalTime, MAX_PATH);
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); //User
698 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer
699 MultiByteToWideChar(CP_ACP,
700 0,
701 lpData,
702 pevlr->DataLength,
703 szData,
704 MAX_PATH);
705 ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, szData); //Event Text
706
707 dwRead -= pevlr->Length;
708 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
709 }
710
711 dwRecordsToRead--;
712 dwCurrentRecord++;
713 }
714
715 // All events loaded
716 EndDialog(hwndDlg, 0);
717
718 StringCchPrintfExW(szWindowTitle,
719 sizeof(szWindowTitle) / sizeof(WCHAR),
720 &lpTitleTemplateEnd,
721 &cchRemaining,
722 0,
723 szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */
724 /* lpComputerName can be NULL here if no records was read */
725 dwMaxLength = cchRemaining;
726 if (!lpComputerName)
727 GetComputerNameW(lpTitleTemplateEnd, &dwMaxLength);
728 else
729 StringCchCopyW(lpTitleTemplateEnd, dwMaxLength, lpComputerName);
730
731 StringCbPrintfW(szStatusText, sizeof(szStatusText), szStatusBarTemplate, lpLogName, dwTotalRecords);
732
733 // Update the status bar
734 SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
735
736 // Set the window title
737 SetWindowTextW(hwndMainWindow, szWindowTitle);
738
739 // Resume list view redraw
740 SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
741
742 // Close the event log.
743 CloseEventLog(hEventLog);
744
745 return TRUE;
746 }
747
748
749 VOID
750 SaveProtocol(VOID)
751 {
752 HANDLE hEventLog;
753 WCHAR szFileName[MAX_PATH];
754
755 ZeroMemory(szFileName, sizeof(szFileName));
756
757 sfn.lpstrFile = szFileName;
758 sfn.nMaxFile = MAX_PATH;
759
760 if (!GetSaveFileNameW(&sfn))
761 {
762 return;
763 }
764
765 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
766 if (!hEventLog)
767 {
768 ShowLastWin32Error();
769 return;
770 }
771
772 if (!BackupEventLogW(hEventLog, szFileName))
773 {
774 ShowLastWin32Error();
775 }
776
777 CloseEventLog(hEventLog);
778 }
779
780
781 BOOL
782 ClearEvents(VOID)
783 {
784 HANDLE hEventLog;
785 WCHAR szFileName[MAX_PATH];
786 WCHAR szMessage[MAX_LOADSTRING];
787
788 ZeroMemory(szFileName, sizeof(szFileName));
789 ZeroMemory(szMessage, sizeof(szMessage));
790
791 LoadStringW(hInst, IDS_CLEAREVENTS_MSG, szMessage, MAX_LOADSTRING);
792
793 sfn.lpstrFile = szFileName;
794 sfn.nMaxFile = MAX_PATH;
795
796 switch (MessageBoxW(hwndMainWindow, szMessage, szTitle, MB_YESNOCANCEL | MB_ICONINFORMATION))
797 {
798 case IDCANCEL:
799 {
800 return FALSE;
801 }
802
803 case IDNO:
804 {
805 sfn.lpstrFile = NULL;
806 break;
807 }
808
809 case IDYES:
810 {
811 if (!GetSaveFileNameW(&sfn))
812 {
813 return FALSE;
814 }
815 break;
816 }
817 }
818
819 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
820 if (!hEventLog)
821 {
822 ShowLastWin32Error();
823 return FALSE;
824 }
825
826 if (!ClearEventLogW(hEventLog, sfn.lpstrFile))
827 {
828 ShowLastWin32Error();
829 CloseEventLog(hEventLog);
830 return FALSE;
831 }
832
833 CloseEventLog(hEventLog);
834
835 return TRUE;
836 }
837
838
839 VOID
840 Refresh(VOID)
841 {
842 QueryEventMessages(lpComputerName,
843 lpSourceLogName);
844 }
845
846
847 ATOM
848 MyRegisterClass(HINSTANCE hInstance)
849 {
850 WNDCLASSEXW wcex;
851
852 wcex.cbSize = sizeof(WNDCLASSEX);
853
854 wcex.style = 0;
855 wcex.lpfnWndProc = WndProc;
856 wcex.cbClsExtra = 0;
857 wcex.cbWndExtra = 0;
858 wcex.hInstance = hInstance;
859 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
860 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
861 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
862 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
863 wcex.lpszClassName = szWindowClass;
864 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
865
866 return RegisterClassExW(&wcex);
867 }
868
869
870 VOID
871 GetDisplayNameFile(IN LPCWSTR lpLogName,
872 OUT PWCHAR lpModuleName)
873 {
874 HKEY hKey;
875 WCHAR *KeyPath;
876 WCHAR szModuleName[MAX_PATH];
877 DWORD cbData;
878 DWORD cbKeyPath;
879
880 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
881 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
882 if (!KeyPath)
883 {
884 return;
885 }
886
887 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
888 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
889
890 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
891 {
892 HeapFree(GetProcessHeap(), 0, KeyPath);
893 return;
894 }
895
896 cbData = sizeof(szModuleName);
897 if (RegQueryValueExW(hKey, L"DisplayNameFile", NULL, NULL, (LPBYTE)szModuleName, &cbData) == ERROR_SUCCESS)
898 {
899 ExpandEnvironmentStringsW(szModuleName, lpModuleName, MAX_PATH);
900 }
901
902 RegCloseKey(hKey);
903 HeapFree(GetProcessHeap(), 0, KeyPath);
904 }
905
906
907 DWORD
908 GetDisplayNameID(IN LPCWSTR lpLogName)
909 {
910 HKEY hKey;
911 WCHAR *KeyPath;
912 DWORD dwMessageID = 0;
913 DWORD cbData;
914 DWORD cbKeyPath;
915
916 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
917 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
918 if (!KeyPath)
919 {
920 return 0;
921 }
922
923 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
924 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
925
926 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
927 {
928 HeapFree(GetProcessHeap(), 0, KeyPath);
929 return 0;
930 }
931
932 cbData = sizeof(dwMessageID);
933 RegQueryValueExW(hKey, L"DisplayNameID", NULL, NULL, (LPBYTE)&dwMessageID, &cbData);
934
935 RegCloseKey(hKey);
936 HeapFree(GetProcessHeap(), 0, KeyPath);
937
938 return dwMessageID;
939 }
940
941
942 VOID
943 BuildLogList(void)
944 {
945 HKEY hKey;
946 DWORD lpcName;
947 DWORD dwIndex;
948 DWORD dwMessageID;
949 DWORD dwMaxKeyLength;
950 WCHAR szModuleName[MAX_PATH];
951 LPWSTR lpDisplayName;
952 HANDLE hLibrary = NULL;
953
954 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, EVENTLOG_BASE_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
955 {
956 return;
957 }
958
959 if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumLogs, &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
960 {
961 RegCloseKey(hKey);
962 return;
963 }
964
965 if (!dwNumLogs)
966 {
967 RegCloseKey(hKey);
968 return;
969 }
970
971 LogNames = HeapAlloc(GetProcessHeap(), 0, (dwNumLogs + 1) * sizeof(WCHAR*));
972
973 if (!LogNames)
974 {
975 RegCloseKey(hKey);
976 return;
977 }
978
979 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
980 {
981 LogNames[dwIndex] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((dwMaxKeyLength + 1) * sizeof(WCHAR)));
982
983 if (LogNames[dwIndex] != NULL)
984 {
985 lpcName = dwMaxKeyLength + 1;
986
987 if (RegEnumKeyExW(hKey, dwIndex, LogNames[dwIndex], &lpcName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
988 {
989 lpDisplayName = NULL;
990
991 ZeroMemory(szModuleName, sizeof(szModuleName));
992 GetDisplayNameFile(LogNames[dwIndex], szModuleName);
993 dwMessageID = GetDisplayNameID(LogNames[dwIndex]);
994
995 hLibrary = LoadLibraryExW(szModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
996 if (hLibrary != NULL)
997 {
998 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, hLibrary, dwMessageID, 0, (LPWSTR)&lpDisplayName, 0, NULL);
999 FreeLibrary(hLibrary);
1000 }
1001
1002 if (lpDisplayName)
1003 {
1004 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, lpDisplayName);
1005 }
1006 else
1007 {
1008 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, LogNames[dwIndex]);
1009 }
1010
1011 LocalFree(lpDisplayName);
1012 }
1013 }
1014 }
1015
1016 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_SEPARATOR, ID_FIRST_LOG + dwIndex + 1, NULL);
1017
1018 RegCloseKey(hKey);
1019
1020 return;
1021 }
1022
1023
1024 VOID
1025 FreeLogList(void)
1026 {
1027 DWORD dwIndex;
1028
1029 if (!LogNames)
1030 {
1031 return;
1032 }
1033
1034 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
1035 {
1036 if (LogNames[dwIndex])
1037 {
1038 HeapFree(GetProcessHeap(), 0, LogNames[dwIndex]);
1039 }
1040
1041 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex, MF_BYCOMMAND);
1042 }
1043
1044 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex + 1, MF_BYCOMMAND);
1045
1046 HeapFree(GetProcessHeap(), 0, LogNames);
1047
1048 dwNumLogs = 0;
1049
1050 return;
1051 }
1052
1053
1054 BOOL
1055 InitInstance(HINSTANCE hInstance,
1056 int nCmdShow)
1057 {
1058 HIMAGELIST hSmall;
1059 LVCOLUMNW lvc = {0};
1060 WCHAR szTemp[256];
1061
1062 hInst = hInstance; // Store instance handle in our global variable
1063
1064 hwndMainWindow = CreateWindowW(szWindowClass,
1065 szTitle,
1066 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
1067 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
1068 NULL,
1069 NULL,
1070 hInstance,
1071 NULL);
1072 if (!hwndMainWindow)
1073 {
1074 return FALSE;
1075 }
1076
1077 hwndStatus = CreateWindowExW(0, // no extended styles
1078 STATUSCLASSNAMEW, // status bar
1079 L"Done.", // no text
1080 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
1081 0, 0, 0, 0, // x, y, cx, cy
1082 hwndMainWindow, // parent window
1083 (HMENU)100, // window ID
1084 hInstance, // instance
1085 NULL); // window data
1086
1087 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
1088 // and WS_BORDER to create the normal "sunken" look. Also note that
1089 // LVS_EX_ styles cannot be set in CreateWindowEx().
1090 hwndListView = CreateWindowExW(WS_EX_CLIENTEDGE,
1091 WC_LISTVIEWW,
1092 L"",
1093 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
1094 0,
1095 0,
1096 243,
1097 200,
1098 hwndMainWindow,
1099 NULL,
1100 hInstance,
1101 NULL);
1102
1103 // After the ListView is created, we can add extended list view styles.
1104 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
1105
1106 // Create the ImageList
1107 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1108 GetSystemMetrics(SM_CYSMICON),
1109 ILC_MASK,
1110 1,
1111 1);
1112
1113 // Add event type icons to ImageList
1114 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
1115 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
1116 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
1117
1118 // Assign ImageList to List View
1119 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
1120
1121 // Now set up the listview with its columns.
1122 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
1123 lvc.cx = 90;
1124 LoadStringW(hInstance,
1125 IDS_COLUMNTYPE,
1126 szTemp,
1127 sizeof(szTemp) / sizeof(WCHAR));
1128 lvc.pszText = szTemp;
1129 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
1130
1131 lvc.cx = 70;
1132 LoadStringW(hInstance,
1133 IDS_COLUMNDATE,
1134 szTemp,
1135 sizeof(szTemp) / sizeof(WCHAR));
1136 lvc.pszText = szTemp;
1137 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
1138
1139 lvc.cx = 70;
1140 LoadStringW(hInstance,
1141 IDS_COLUMNTIME,
1142 szTemp,
1143 sizeof(szTemp) / sizeof(WCHAR));
1144 lvc.pszText = szTemp;
1145 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
1146
1147 lvc.cx = 150;
1148 LoadStringW(hInstance,
1149 IDS_COLUMNSOURCE,
1150 szTemp,
1151 sizeof(szTemp) / sizeof(WCHAR));
1152 lvc.pszText = szTemp;
1153 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
1154
1155 lvc.cx = 100;
1156 LoadStringW(hInstance,
1157 IDS_COLUMNCATEGORY,
1158 szTemp,
1159 sizeof(szTemp) / sizeof(WCHAR));
1160 lvc.pszText = szTemp;
1161 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
1162
1163 lvc.cx = 60;
1164 LoadStringW(hInstance,
1165 IDS_COLUMNEVENT,
1166 szTemp,
1167 sizeof(szTemp) / sizeof(WCHAR));
1168 lvc.pszText = szTemp;
1169 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
1170
1171 lvc.cx = 120;
1172 LoadStringW(hInstance,
1173 IDS_COLUMNUSER,
1174 szTemp,
1175 sizeof(szTemp) / sizeof(WCHAR));
1176 lvc.pszText = szTemp;
1177 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
1178
1179 lvc.cx = 100;
1180 LoadStringW(hInstance,
1181 IDS_COLUMNCOMPUTER,
1182 szTemp,
1183 sizeof(szTemp) / sizeof(WCHAR));
1184 lvc.pszText = szTemp;
1185 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
1186
1187 lvc.cx = 0;
1188 LoadStringW(hInstance,
1189 IDS_COLUMNEVENTDATA,
1190 szTemp,
1191 sizeof(szTemp) / sizeof(WCHAR));
1192 lvc.pszText = szTemp;
1193 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
1194
1195 // Initialize the save Dialog
1196 ZeroMemory(&sfn, sizeof(sfn));
1197 ZeroMemory(szSaveFilter, sizeof(szSaveFilter));
1198
1199 LoadStringW(hInst, IDS_SAVE_FILTER, szSaveFilter, MAX_LOADSTRING);
1200
1201 sfn.lStructSize = sizeof(sfn);
1202 sfn.hwndOwner = hwndMainWindow;
1203 sfn.hInstance = hInstance;
1204 sfn.lpstrFilter = szSaveFilter;
1205 sfn.lpstrInitialDir = NULL;
1206 sfn.Flags = OFN_HIDEREADONLY | OFN_SHAREAWARE;
1207 sfn.lpstrDefExt = NULL;
1208
1209 ShowWindow(hwndMainWindow, nCmdShow);
1210 UpdateWindow(hwndMainWindow);
1211
1212 BuildLogList();
1213
1214 QueryEventMessages(lpComputerName, LogNames[0]);
1215
1216 CheckMenuRadioItem(GetMenu(hwndMainWindow), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, ID_FIRST_LOG, MF_BYCOMMAND);
1217
1218 return TRUE;
1219 }
1220
1221
1222 LRESULT CALLBACK
1223 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1224 {
1225 RECT rect;
1226 NMHDR *hdr;
1227
1228 switch (message)
1229 {
1230 case WM_CREATE:
1231 hMainMenu = GetMenu(hWnd);
1232 break;
1233
1234 case WM_NOTIFY:
1235 switch (((LPNMHDR)lParam)->code)
1236 {
1237 case NM_DBLCLK :
1238 hdr = (NMHDR FAR*)lParam;
1239 if (hdr->hwndFrom == hwndListView)
1240 {
1241 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
1242
1243 if (lpnmitem->iItem != -1)
1244 {
1245 DialogBox(hInst,
1246 MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG),
1247 hWnd,
1248 EventDetails);
1249 }
1250 }
1251 break;
1252 }
1253 break;
1254
1255 case WM_COMMAND:
1256 // Parse the menu selections:
1257
1258 if ((LOWORD(wParam) >= ID_FIRST_LOG) && (LOWORD(wParam) <= ID_FIRST_LOG + dwNumLogs))
1259 {
1260 if (LogNames[LOWORD(wParam) - ID_FIRST_LOG])
1261 {
1262 if (QueryEventMessages(lpComputerName, LogNames[LOWORD(wParam) - ID_FIRST_LOG]))
1263 {
1264 CheckMenuRadioItem(GetMenu(hWnd), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, LOWORD(wParam), MF_BYCOMMAND);
1265 }
1266 }
1267 }
1268 else
1269
1270 switch (LOWORD(wParam))
1271 {
1272 case ID_SAVE_PROTOCOL:
1273 SaveProtocol();
1274 break;
1275
1276 case ID_CLEAR_EVENTS:
1277 if (ClearEvents())
1278 {
1279 Refresh();
1280 }
1281 break;
1282
1283 case IDM_REFRESH:
1284 Refresh();
1285 break;
1286
1287 case IDM_ABOUT:
1288 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
1289 break;
1290
1291 case IDM_HELP:
1292 MessageBoxW(hwndMainWindow,
1293 L"Help not implemented yet!",
1294 L"Event Log",
1295 MB_OK | MB_ICONINFORMATION);
1296 break;
1297
1298 case IDM_EXIT:
1299 DestroyWindow(hWnd);
1300 break;
1301
1302 default:
1303 return DefWindowProc(hWnd, message, wParam, lParam);
1304 }
1305 break;
1306
1307 case WM_SIZE:
1308 {
1309 // Gets the window rectangle
1310 GetClientRect(hWnd, &rect);
1311
1312 // Relocate the listview
1313 MoveWindow(hwndListView,
1314 0,
1315 0,
1316 rect.right,
1317 rect.bottom - 20,
1318 1);
1319
1320 // Resize the statusbar;
1321 SendMessage(hwndStatus, message, wParam, lParam);
1322 }
1323 break;
1324 case WM_DESTROY:
1325 FreeRecords();
1326 FreeLogList();
1327 PostQuitMessage(0);
1328 break;
1329
1330 default:
1331 return DefWindowProc(hWnd, message, wParam, lParam);
1332 }
1333
1334 return 0;
1335 }
1336
1337
1338 // Message handler for about box.
1339 INT_PTR CALLBACK
1340 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1341 {
1342 UNREFERENCED_PARAMETER(lParam);
1343 switch (message)
1344 {
1345 case WM_INITDIALOG:
1346 {
1347 return (INT_PTR)TRUE;
1348 }
1349
1350 case WM_COMMAND:
1351 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1352 {
1353 EndDialog(hDlg, LOWORD(wParam));
1354 return (INT_PTR)TRUE;
1355 }
1356 break;
1357 }
1358
1359 return (INT_PTR)FALSE;
1360 }
1361
1362 VOID
1363 DisplayEvent(HWND hDlg)
1364 {
1365 WCHAR szEventType[MAX_PATH];
1366 WCHAR szTime[MAX_PATH];
1367 WCHAR szDate[MAX_PATH];
1368 WCHAR szUser[MAX_PATH];
1369 WCHAR szComputer[MAX_PATH];
1370 WCHAR szSource[MAX_PATH];
1371 WCHAR szCategory[MAX_PATH];
1372 WCHAR szEventID[MAX_PATH];
1373 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1374 WCHAR szEventData[MAX_PATH];
1375 BOOL bEventData = FALSE;
1376 LVITEMW li;
1377 EVENTLOGRECORD* pevlr;
1378 int iIndex;
1379
1380 // Get index of selected item
1381 iIndex = (int)SendMessage (hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1382
1383 li.mask = LVIF_PARAM;
1384 li.iItem = iIndex;
1385 li.iSubItem = 0;
1386
1387 (void)ListView_GetItem(hwndListView, &li);
1388
1389 pevlr = (EVENTLOGRECORD*)li.lParam;
1390
1391 if (iIndex != -1)
1392 {
1393 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType) / sizeof(WCHAR));
1394 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate) / sizeof(WCHAR));
1395 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime) / sizeof(WCHAR));
1396 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource) / sizeof(WCHAR));
1397 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory) / sizeof(WCHAR));
1398 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID) / sizeof(WCHAR));
1399 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser) / sizeof(WCHAR));
1400 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer) / sizeof(WCHAR));
1401
1402 bEventData = !(pevlr->DataLength == 0);
1403
1404 if (pevlr->DataLength > 0)
1405 {
1406 MultiByteToWideChar(CP_ACP,
1407 0,
1408 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1409 pevlr->DataLength,
1410 szEventData,
1411 MAX_PATH);
1412 }
1413
1414 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1415
1416 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1417 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1418
1419 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
1420 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
1421
1422 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
1423 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1424 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1425 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1426 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
1427 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1428 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1429 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, szEventData);
1430 }
1431 else
1432 {
1433 MessageBoxW(NULL,
1434 L"No Items in ListView",
1435 L"Error",
1436 MB_OK | MB_ICONINFORMATION);
1437 }
1438 }
1439
1440
1441 static
1442 INT_PTR CALLBACK
1443 StatusMessageWindowProc(IN HWND hwndDlg,
1444 IN UINT uMsg,
1445 IN WPARAM wParam,
1446 IN LPARAM lParam)
1447 {
1448 UNREFERENCED_PARAMETER(wParam);
1449
1450 switch (uMsg)
1451 {
1452 case WM_INITDIALOG:
1453 {
1454 return TRUE;
1455 }
1456 }
1457 return FALSE;
1458 }
1459
1460
1461 // Message handler for event details box.
1462 INT_PTR CALLBACK
1463 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1464 {
1465 UNREFERENCED_PARAMETER(lParam);
1466
1467 switch (message)
1468 {
1469 case WM_INITDIALOG:
1470 // Show event info on dialog box
1471 DisplayEvent(hDlg);
1472 return (INT_PTR)TRUE;
1473
1474 case WM_COMMAND:
1475 switch (LOWORD(wParam))
1476 {
1477 case IDOK:
1478 case IDCANCEL:
1479 EndDialog(hDlg, LOWORD(wParam));
1480 return (INT_PTR)TRUE;
1481
1482 case IDPREVIOUS:
1483 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1484
1485 // Show event info on dialog box
1486 DisplayEvent(hDlg);
1487 return (INT_PTR)TRUE;
1488
1489 case IDNEXT:
1490 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1491
1492 // Show event info on dialog box
1493 DisplayEvent(hDlg);
1494 return (INT_PTR)TRUE;
1495
1496 case IDC_BYTESRADIO:
1497 return (INT_PTR)TRUE;
1498
1499 case IDC_WORDRADIO:
1500 return (INT_PTR)TRUE;
1501
1502 case IDHELP:
1503 MessageBoxW(hDlg,
1504 L"Help not implemented yet!",
1505 L"Event Log",
1506 MB_OK | MB_ICONINFORMATION);
1507 return (INT_PTR)TRUE;
1508
1509 default:
1510 break;
1511 }
1512 break;
1513 }
1514
1515 return (INT_PTR)FALSE;
1516 }