59a5047a4ca5da700e18166f3aeae8fe0efbc90a
[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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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 "eventvwr.h"
27 #include <windows.h> // Standard windows include file
28 #include <commctrl.h> // For ListView control APIs
29 #include <tchar.h> // For TCHAR and string functions.
30 #include <stdio.h>
31 #include <time.h>
32
33 #if _MSC_VER
34 #pragma warning(disable: 4996) // 'strdup' was declared deprecated
35 #define _CRT_SECURE_NO_DEPRECATE // all deprecated 'unsafe string functions
36 #endif
37
38 static const LPTSTR EVENT_SOURCE_APPLICATION = _TEXT("Application");
39 static const LPTSTR EVENT_SOURCE_SECURITY = _TEXT("Security");
40 static const LPTSTR EVENT_SOURCE_SYSTEM = _TEXT("System");
41 static const TCHAR szWindowClass[] = _TEXT("EVENTVWR"); // the main window class name
42
43 //MessageFile message buffer size
44 #define EVENT_MESSAGE_EVENTTEXT_BUFFER 1024*10
45 #define EVENT_MESSAGE_FILE_BUFFER 1024*10
46 #define EVENT_DLL_SEPARATOR _TEXT(";")
47 #define EVENT_MESSAGE_FILE _TEXT("EventMessageFile")
48 #define EVENT_CATEGORY_MESSAGE_FILE _TEXT("CategoryMessageFile")
49 #define EVENT_PARAMETER_MESSAGE_FILE _TEXT("ParameterMessageFile")
50
51 #define MAX_LOADSTRING 255
52
53 // Global Variables:
54 HINSTANCE hInst; // current instance
55 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
56
57 // Globals
58 HWND hwndMainWindow; // Main window
59 HWND hwndListView; // ListView control
60 HWND hwndStatus; // Status bar
61
62 LPTSTR lpSourceLogName = NULL;
63 LPTSTR lpComputerName = NULL;
64
65 // Forward declarations of functions included in this code module:
66 ATOM MyRegisterClass(HINSTANCE hInstance);
67 BOOL InitInstance(HINSTANCE, int);
68 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
69 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
70 INT_PTR CALLBACK EventDetails(HWND, UINT, WPARAM, LPARAM);
71 static INT_PTR CALLBACK StatusMessageWindowProc (HWND, UINT, WPARAM, LPARAM);
72
73
74 int APIENTRY
75 _tWinMain(HINSTANCE hInstance,
76 HINSTANCE hPrevInstance,
77 LPTSTR lpCmdLine,
78 int nCmdShow)
79 {
80 MSG msg;
81 HACCEL hAccelTable;
82 INITCOMMONCONTROLSEX iccx;
83
84 UNREFERENCED_PARAMETER(hPrevInstance);
85 UNREFERENCED_PARAMETER(lpCmdLine);
86
87 // Whenever any of the common controls are used in your app,
88 // you must call InitCommonControlsEx() to register the classes
89 // for those controls.
90 iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
91 iccx.dwICC = ICC_LISTVIEW_CLASSES;
92 InitCommonControlsEx(&iccx);
93
94 // Initialize global strings
95 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
96 MyRegisterClass(hInstance);
97
98 // Perform application initialization:
99 if (!InitInstance(hInstance, nCmdShow))
100 {
101 return FALSE;
102 }
103
104 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EVENTVWR));
105
106 // Main message loop:
107 while (GetMessage(&msg, NULL, 0, 0))
108 {
109 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
110 {
111 TranslateMessage(&msg);
112 DispatchMessage(&msg);
113 }
114 }
115
116 return (int)msg.wParam;
117 }
118
119
120 VOID
121 EventTimeToSystemTime(DWORD EventTime,
122 SYSTEMTIME *pSystemTime)
123 {
124 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
125 FILETIME ftLocal;
126 union
127 {
128 FILETIME ft;
129 ULONGLONG ll;
130 } u1970, uUCT;
131
132 uUCT.ft.dwHighDateTime = 0;
133 uUCT.ft.dwLowDateTime = EventTime;
134 SystemTimeToFileTime(&st1970, &u1970.ft);
135 uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
136 FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
137 FileTimeToSystemTime(&ftLocal, pSystemTime);
138 }
139
140
141 void
142 TrimNulls(LPTSTR s)
143 {
144 TCHAR *c;
145
146 if (s != NULL)
147 {
148 c = s + _tcslen(s) - 1;
149 while (c >= s && _istspace(*c))
150 --c;
151 *++c = _TEXT('\0');
152 }
153 }
154
155
156 BOOL
157 GetEventMessageFileDLL(IN LPCTSTR lpLogName,
158 IN LPCTSTR SourceName,
159 IN LPCTSTR EntryName,
160 OUT LPTSTR ExpandedName)
161 {
162 DWORD dwSize;
163 BYTE szModuleName[MAX_PATH];
164 TCHAR szKeyName[MAX_PATH];
165 HKEY hAppKey = NULL;
166 HKEY hSourceKey = NULL;
167 BOOL bReturn = FALSE; // Return
168
169 _tcscpy(szKeyName, _TEXT("SYSTEM\\CurrentControlSet\\Services\\EventLog"));
170 _tcscat(szKeyName, _TEXT("\\"));
171 _tcscat(szKeyName, lpLogName);
172
173 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
174 szKeyName,
175 0,
176 KEY_READ,
177 &hAppKey) == ERROR_SUCCESS)
178 {
179 if (RegOpenKeyEx(hAppKey,
180 SourceName,
181 0,
182 KEY_READ,
183 &hSourceKey) == ERROR_SUCCESS)
184 {
185 dwSize = MAX_PATH;
186 if (RegQueryValueEx(hSourceKey,
187 EntryName,
188 NULL,
189 NULL,
190 (LPBYTE)szModuleName,
191 &dwSize) == ERROR_SUCCESS)
192 {
193 // Returns a string containing the requested substituted environment variable.
194 ExpandEnvironmentStrings((LPCTSTR)szModuleName, ExpandedName, MAX_PATH);
195
196 // Succesfull
197 bReturn = TRUE;
198 }
199 }
200 }
201 else
202 {
203 MessageBox(NULL,
204 _TEXT("Registry access failed!"),
205 _TEXT("Event Log"),
206 MB_OK | MB_ICONINFORMATION);
207 }
208
209 if (hSourceKey != NULL)
210 RegCloseKey(hSourceKey);
211
212 if (hAppKey != NULL)
213 RegCloseKey(hAppKey);
214
215 return bReturn;
216 }
217
218
219 BOOL
220 GetEventCategory(IN LPCTSTR KeyName,
221 IN LPCTSTR SourceName,
222 IN EVENTLOGRECORD *pevlr,
223 OUT LPTSTR CategoryName)
224 {
225 HANDLE hLibrary = NULL;
226 TCHAR szMessageDLL[MAX_PATH];
227 LPVOID lpMsgBuf = NULL;
228
229 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_CATEGORY_MESSAGE_FILE , szMessageDLL))
230 {
231 hLibrary = LoadLibraryEx(szMessageDLL,
232 NULL,
233 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
234 if (hLibrary != NULL)
235 {
236 // Retrieve the message string.
237 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
238 hLibrary,
239 pevlr->EventCategory,
240 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
241 (LPTSTR)&lpMsgBuf,
242 EVENT_MESSAGE_FILE_BUFFER,
243 NULL) != 0)
244 {
245 if (lpMsgBuf)
246 {
247 // Trim the string
248 TrimNulls((LPTSTR)lpMsgBuf);
249
250 // Copy the category name
251 _tcscpy(CategoryName, (LPCTSTR)lpMsgBuf);
252 }
253 else
254 {
255 _tcscpy(CategoryName, (LPCTSTR)lpMsgBuf);
256 }
257 }
258 else
259 {
260 _tcscpy(CategoryName, _TEXT("None"));
261 }
262
263 if (hLibrary != NULL)
264 FreeLibrary(hLibrary);
265
266 // Free the buffer allocated by FormatMessage
267 if (lpMsgBuf)
268 LocalFree(lpMsgBuf);
269
270 return TRUE;
271 }
272 }
273
274 _tcscpy(CategoryName, _TEXT("None"));
275
276 return FALSE;
277 }
278
279
280 BOOL
281 GetEventMessage(IN LPCTSTR KeyName,
282 IN LPCTSTR SourceName,
283 IN EVENTLOGRECORD *pevlr,
284 OUT LPTSTR EventText)
285 {
286 DWORD i;
287 HANDLE hLibrary = NULL;
288 TCHAR SourceModuleName[1000];
289 TCHAR ParameterModuleName[1000];
290 LPTSTR lpMsgBuf = NULL;
291 TCHAR szStringIDNotFound[MAX_LOADSTRING];
292 LPTSTR szDll;
293 LPTSTR szMessage;
294 LPTSTR *szArguments;
295 BOOL bDone = FALSE;
296
297 /* TODO : GetEventMessageFileDLL can return a comma separated list of DLLs */
298 if (GetEventMessageFileDLL (KeyName , SourceName, EVENT_MESSAGE_FILE , SourceModuleName))
299 {
300 // Get the event message
301 szMessage = (LPTSTR)((LPBYTE)pevlr + pevlr->StringOffset);
302
303 // Allocate space for parameters
304 szArguments = (LPTSTR*)malloc(sizeof(LPVOID) * pevlr->NumStrings);
305 if (!szArguments)
306 {
307 return FALSE;
308 }
309
310 for (i = 0; i < pevlr->NumStrings ; i++)
311 {
312 if (_tcsstr(szMessage , _TEXT("%%")))
313 {
314 if (GetEventMessageFileDLL(KeyName , SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
315 {
316 // Not yet support for reading messages from parameter message DLL
317 }
318
319 szArguments[i] = szMessage;
320 szMessage += _tcslen(szMessage) + 1;
321 }
322 else
323 {
324 szArguments[i] = szMessage;
325 szMessage += _tcslen(szMessage) + 1;
326 }
327 }
328
329 szDll = _tcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
330 while ((szDll != NULL) && (!bDone))
331 {
332 hLibrary = LoadLibraryEx(szDll,
333 NULL,
334 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
335 if (hLibrary == NULL)
336 {
337 // The DLL could not be loaded try the next one (if any)
338 szDll = _tcstok(NULL, EVENT_DLL_SEPARATOR);
339 }
340 else
341 {
342 // Retrieve the message string.
343 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
344 FORMAT_MESSAGE_ALLOCATE_BUFFER |
345 FORMAT_MESSAGE_FROM_HMODULE |
346 FORMAT_MESSAGE_ARGUMENT_ARRAY,
347 hLibrary,
348 pevlr->EventID,
349 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
350 (LPTSTR)&lpMsgBuf,
351 0,
352 (va_list*)szArguments) == 0)
353 {
354 // We haven't found the string , get next DLL (if any)
355 szDll = _tcstok(NULL, EVENT_DLL_SEPARATOR);
356 }
357 else
358 {
359 if (lpMsgBuf)
360 {
361 // The ID was found and the message was formated
362 bDone = TRUE;
363
364 // Trim the string
365 TrimNulls((LPTSTR)lpMsgBuf);
366
367 // Copy the event text
368 _tcscpy(EventText ,lpMsgBuf);
369 }
370 }
371
372 FreeLibrary(hLibrary);
373 }
374 }
375
376 if (!bDone)
377 {
378 LoadString(hInst, IDC_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
379 wsprintf(EventText, szStringIDNotFound, (DWORD)(pevlr->EventID & 0xFFFF), SourceName);
380 }
381
382 free(szArguments);
383
384 // No more dlls to try , return result
385 return bDone;
386 }
387
388 LoadString(hInst, IDC_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
389 wsprintf(EventText, szStringIDNotFound, (DWORD)(pevlr->EventID & 0xFFFF), SourceName);
390
391 return FALSE;
392 }
393
394
395 VOID
396 GetEventType(IN WORD dwEventType,
397 OUT LPTSTR eventTypeText)
398 {
399 switch (dwEventType)
400 {
401 case EVENTLOG_ERROR_TYPE:
402 LoadString(hInst, IDC_EVENTLOG_ERROR_TYPE, eventTypeText, MAX_LOADSTRING);
403 break;
404 case EVENTLOG_WARNING_TYPE:
405 LoadString(hInst, IDC_EVENTLOG_WARNING_TYPE, eventTypeText, MAX_LOADSTRING);
406 break;
407 case EVENTLOG_INFORMATION_TYPE:
408 LoadString(hInst, IDC_EVENTLOG_INFORMATION_TYPE, eventTypeText, MAX_LOADSTRING);
409 break;
410 case EVENTLOG_AUDIT_SUCCESS:
411 LoadString(hInst, IDC_EVENTLOG_AUDIT_SUCCESS, eventTypeText, MAX_LOADSTRING);
412 break;
413 case EVENTLOG_AUDIT_FAILURE:
414 LoadString(hInst, IDC_EVENTLOG_AUDIT_FAILURE, eventTypeText, MAX_LOADSTRING);
415 break;
416 case EVENTLOG_SUCCESS:
417 LoadString(hInst, IDC_EVENTLOG_SUCCESS, eventTypeText, MAX_LOADSTRING);
418 break;
419 default:
420 LoadString(hInst, IDC_EVENTLOG_UNKNOWN_TYPE, eventTypeText, MAX_LOADSTRING);
421 break;
422 }
423 }
424
425 BOOL
426 GetEventUserName(EVENTLOGRECORD *pelr,
427 OUT LPTSTR pszUser)
428 {
429 PSID lpSid;
430 TCHAR szName[1024];
431 TCHAR szDomain[1024];
432 SID_NAME_USE peUse;
433 DWORD cbName = 1024;
434 DWORD cbDomain = 1024;
435
436 // Point to the SID.
437 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
438
439 // User SID
440 if (pelr->UserSidLength > 0)
441 {
442 if (LookupAccountSid(NULL,
443 lpSid,
444 szName,
445 &cbName,
446 szDomain,
447 &cbDomain,
448 &peUse))
449 {
450 _tcscpy(pszUser, szName);
451 return TRUE;
452 }
453 }
454
455 return FALSE;
456 }
457
458
459 static DWORD WINAPI
460 ShowStatusMessageThread(IN LPVOID lpParameter)
461 {
462 HWND *phWnd = (HWND *)lpParameter;
463 HWND hWnd;
464 MSG Msg;
465
466 hWnd = CreateDialogParam(hInst,
467 MAKEINTRESOURCE(IDD_PROGRESSBOX),
468 GetDesktopWindow(),
469 StatusMessageWindowProc,
470 (LPARAM)NULL);
471 if (!hWnd)
472 return 0;
473
474 *phWnd = hWnd;
475
476 ShowWindow(hWnd, SW_SHOW);
477
478 /* Message loop for the Status window */
479 while (GetMessage(&Msg, NULL, 0, 0))
480 {
481 TranslateMessage(&Msg);
482 DispatchMessage(&Msg);
483 }
484
485 return 0;
486 }
487
488
489 VOID
490 QueryEventMessages(LPTSTR lpMachineName,
491 LPTSTR lpLogName)
492 {
493 HWND hwndDlg;
494 HANDLE hEventLog;
495 EVENTLOGRECORD *pevlr;
496 BYTE bBuffer[MAX_PATH];
497 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords, dwCurrentRecord = 1, dwRecordsToRead = 0, dwFlags;
498 LPTSTR lpSourceName;
499 LPTSTR lpComputerName;
500 LPTSTR lpEventStr;
501 LPTSTR lpData;
502 BOOL bResult = TRUE; // Read succeeded.
503
504 TCHAR szWindowTitle[MAX_PATH];
505 TCHAR szStatusText[MAX_PATH];
506 TCHAR szLocalDate[MAX_PATH];
507 TCHAR szLocalTime[MAX_PATH];
508 TCHAR szEventID[MAX_PATH];
509 TCHAR szEventTypeText[MAX_PATH];
510 TCHAR szCategoryID[MAX_PATH];
511 TCHAR szUsername[MAX_PATH];
512 TCHAR szEventText[EVENT_MESSAGE_FILE_BUFFER];
513 TCHAR szCategory[MAX_PATH];
514
515 SYSTEMTIME time;
516 LVITEM lviEventItem;
517
518 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
519
520 lpSourceLogName = lpLogName;
521 lpComputerName = lpMachineName;
522
523 // Open the event log.
524 hEventLog = OpenEventLog(lpMachineName,
525 lpLogName);
526 if (hEventLog == NULL)
527 {
528 MessageBox(NULL,
529 _TEXT("Could not open the event log."),
530 _TEXT("Event Log"),
531 MB_OK | MB_ICONINFORMATION);
532 return;
533 }
534
535 // Disable listview redraw
536 SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0);
537
538 // Clear the list view
539 (void)ListView_DeleteAllItems (hwndListView);
540
541 // Initialize the event record buffer.
542 pevlr = (EVENTLOGRECORD *)&bBuffer;
543
544 // Get the record number of the oldest event log record.
545 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
546
547 // Get the total number of event log records.
548 GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords);
549
550 //If we have at least 1000 records show the waiting dialog
551 if (dwTotalRecords > 1000)
552 {
553 CreateThread(NULL,
554 0,
555 ShowStatusMessageThread,
556 (LPVOID)&hwndDlg,
557 0,
558 NULL);
559 }
560
561 while (dwCurrentRecord < dwTotalRecords)
562 {
563 pevlr = (EVENTLOGRECORD*)malloc(MAX_PATH);
564
565 bResult = ReadEventLog(hEventLog, // Event log handle
566 dwFlags, // Sequential read
567 0, // Ignored for sequential read
568 pevlr, // Pointer to buffer
569 MAX_PATH, // Size of buffer
570 &dwRead, // Number of bytes read
571 &dwNeeded); // Bytes in the next record
572 if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
573 {
574 pevlr = (EVENTLOGRECORD*)malloc (dwNeeded);
575
576 ReadEventLog(hEventLog, // event log handle
577 dwFlags, // read flags
578 0, // offset; default is 0
579 pevlr, // pointer to buffer
580 dwNeeded, // size of buffer
581 &dwRead, // number of bytes read
582 &dwNeeded); // bytes in next record
583 }
584
585 while (dwRead > 0)
586 {
587 _tcscpy(szUsername , _TEXT("N/A"));
588 _tcscpy(szEventText , _TEXT("N/A"));
589 _tcscpy(szCategory , _TEXT("None"));
590
591 // Get the event source name.
592 lpSourceName = (LPTSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
593
594 // Get the computer name
595 lpComputerName = (LPTSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (_tcslen(lpSourceName) + 1) * sizeof(TCHAR));
596
597 // This ist the data section of the current event
598 lpData = (LPTSTR)((LPBYTE)pevlr + pevlr->DataOffset);
599
600 // This is the text of the current event
601 lpEventStr = (LPTSTR)((LPBYTE)pevlr + pevlr->StringOffset);
602
603 // Compute the event type
604 EventTimeToSystemTime(pevlr->TimeWritten, &time);
605
606 // Get the username that generated the event
607 GetEventUserName(pevlr, szUsername);
608
609 GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, MAX_PATH);
610 GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, szLocalTime, MAX_PATH);
611
612 GetEventType(pevlr->EventType, szEventTypeText);
613 GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory);
614
615 wsprintf(szEventID, _TEXT("%u"), (DWORD)(pevlr->EventID & 0xFFFF));
616 wsprintf(szCategoryID, _TEXT("%u"), (DWORD)(pevlr->EventCategory));
617
618 lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
619 lviEventItem.iItem = 0;
620 lviEventItem.iSubItem = 0;
621 lviEventItem.lParam = (LPARAM)pevlr;
622 lviEventItem.pszText = szEventTypeText;
623
624 switch (pevlr->EventType)
625 {
626 case EVENTLOG_ERROR_TYPE:
627 lviEventItem.iImage = 2;
628 break;
629
630 case EVENTLOG_AUDIT_FAILURE:
631 lviEventItem.iImage = 2;
632 break;
633
634 case EVENTLOG_WARNING_TYPE:
635 lviEventItem.iImage = 1;
636 break;
637
638 case EVENTLOG_INFORMATION_TYPE:
639 lviEventItem.iImage = 0;
640 break;
641
642 case EVENTLOG_AUDIT_SUCCESS:
643 lviEventItem.iImage = 0;
644 break;
645
646 case EVENTLOG_SUCCESS:
647 lviEventItem.iImage = 0;
648 break;
649 }
650
651 lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem);
652
653 ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate);
654 ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime);
655 ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName);
656 ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory);
657 ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID);
658 ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername); //User
659 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer
660 ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, lpData); //Event Text
661
662 dwRead -= pevlr->Length;
663 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
664 }
665
666 dwRecordsToRead--;
667 dwCurrentRecord++;
668
669 pevlr = (EVENTLOGRECORD *)&bBuffer;
670 }
671
672 // All events loaded
673 EndDialog(hwndDlg, 0);
674
675 wsprintf(szWindowTitle, _TEXT("%s - %s Log on \\\\%s"), szTitle, lpLogName, lpComputerName);
676 wsprintf(szStatusText, _TEXT("%s has %d event(s)"), lpLogName, dwTotalRecords);
677
678 // Update the status bar
679 SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
680
681 // Set the window title
682 SetWindowText(hwndMainWindow, szWindowTitle);
683
684 // Resume list view redraw
685 SendMessage(hwndListView, WM_SETREDRAW, TRUE, 0);
686
687 // Close the event log.
688 CloseEventLog(hEventLog);
689 }
690
691
692 VOID
693 Refresh(VOID)
694 {
695 QueryEventMessages(lpComputerName,
696 lpSourceLogName);
697 }
698
699
700 //
701 // FUNCTION: MyRegisterClass()
702 //
703 // PURPOSE: Registers the window class.
704 //
705 // COMMENTS:
706 //
707 // This function and its usage are only necessary if you want this code
708 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
709 // function that was added to Windows 95. It is important to call this function
710 // so that the application will get 'well formed' small icons associated
711 // with it.
712 //
713 ATOM
714 MyRegisterClass(HINSTANCE hInstance)
715 {
716 WNDCLASSEX wcex;
717
718 wcex.cbSize = sizeof(WNDCLASSEX);
719
720 wcex.style = CS_HREDRAW | CS_VREDRAW;
721 wcex.lpfnWndProc = WndProc;
722 wcex.cbClsExtra = 0;
723 wcex.cbWndExtra = 0;
724 wcex.hInstance = hInstance;
725 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
726 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
727 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
728 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
729 wcex.lpszClassName = szWindowClass;
730 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
731
732 return RegisterClassEx(&wcex);
733 }
734
735
736 //
737 // FUNCTION: InitInstance(HINSTANCE, int)
738 //
739 // PURPOSE: Saves instance handle and creates main window
740 //
741 // COMMENTS:
742 //
743 // In this function, we save the instance handle in a global variable and
744 // create and display the main program window.
745 //
746 BOOL
747 InitInstance(HINSTANCE hInstance,
748 int nCmdShow)
749 {
750 HIMAGELIST hSmall;
751 LVCOLUMN lvc = {0};
752
753 hInst = hInstance; // Store instance handle in our global variable
754
755 hwndMainWindow = CreateWindow(szWindowClass,
756 szTitle,
757 WS_OVERLAPPEDWINDOW,
758 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
759 NULL,
760 NULL,
761 hInstance,
762 NULL);
763 if (!hwndMainWindow)
764 {
765 return FALSE;
766 }
767
768 hwndStatus = CreateWindowEx(0, // no extended styles
769 STATUSCLASSNAME, // status bar
770 _TEXT("Done."), // no text
771 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
772 0, 0, 0, 0, // x, y, cx, cy
773 hwndMainWindow, // parent window
774 (HMENU)100, // window ID
775 hInstance, // instance
776 NULL); // window data
777
778 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
779 // and WS_BORDER to create the normal "sunken" look. Also note that
780 // LVS_EX_ styles cannot be set in CreateWindowEx().
781 hwndListView = CreateWindowEx(WS_EX_CLIENTEDGE,
782 WC_LISTVIEW,
783 _TEXT(""),
784 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
785 0,
786 0,
787 243,
788 200,
789 hwndMainWindow,
790 NULL,
791 hInstance,
792 NULL);
793
794 // After the ListView is created, we can add extended list view styles.
795 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
796
797 // Create the ImageList
798 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
799 GetSystemMetrics(SM_CYSMICON),
800 ILC_MASK,
801 1,
802 1);
803
804 // Add event type icons to ImageList
805 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
806 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
807 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
808
809 // Assign ImageList to List View
810 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
811
812 // Now set up the listview with its columns.
813 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
814 lvc.cx = 90;
815 lvc.pszText = _T("Type");
816 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
817
818 lvc.cx = 70;
819 lvc.pszText = _T("Date");
820 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
821
822 lvc.cx = 70;
823 lvc.pszText = _T("Time");
824 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
825
826 lvc.cx = 150;
827 lvc.pszText = _T("Source");
828 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
829
830 lvc.cx = 100;
831 lvc.pszText = _T("Category");
832 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
833
834 lvc.cx = 60;
835 lvc.pszText = _T("Event");
836 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
837
838 lvc.cx = 120;
839 lvc.pszText = _T("User");
840 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
841
842 lvc.cx = 100;
843 lvc.pszText = _T("Computer");
844 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
845
846 lvc.cx = 0;
847 lvc.pszText = _T("Event Data");
848 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
849
850 ShowWindow(hwndMainWindow, nCmdShow);
851 UpdateWindow(hwndMainWindow);
852
853 QueryEventMessages(lpComputerName, // Use the local computer.
854 EVENT_SOURCE_APPLICATION); // The event log category
855
856 return TRUE;
857 }
858
859
860 //
861 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
862 //
863 // PURPOSE: Processes messages for the main window.
864 //
865 // WM_COMMAND - process the application menu
866 // WM_PAINT - Paint the main window
867 // WM_DESTROY - post a quit message and return
868 //
869 //
870 LRESULT CALLBACK
871 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
872 {
873 int wmId, wmEvent;
874 RECT rect;
875 NMHDR *hdr;
876 HMENU hMenu;
877
878 switch (message)
879 {
880 case WM_NOTIFY:
881 switch (((LPNMHDR)lParam)->code)
882 {
883 case NM_DBLCLK :
884 hdr = (NMHDR FAR*)lParam;
885 if (hdr->hwndFrom == hwndListView)
886 {
887 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
888
889 if (lpnmitem->iItem != -1)
890 {
891 DialogBox(hInst, MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG), hWnd, EventDetails);
892 }
893 }
894 break;
895 }
896 break;
897
898 case WM_COMMAND:
899 wmId = LOWORD(wParam);
900 wmEvent = HIWORD(wParam);
901
902 if ((wmId == ID_LOG_APPLICATION) ||
903 (wmId == ID_LOG_SYSTEM) ||
904 (wmId == ID_LOG_SECURITY))
905 {
906 hMenu = GetMenu(hWnd); // get the menu handle. Use it below
907
908 CheckMenuItem(hMenu, ID_LOG_APPLICATION, MF_UNCHECKED);
909 CheckMenuItem(hMenu, ID_LOG_SYSTEM, MF_UNCHECKED);
910 CheckMenuItem (hMenu, ID_LOG_SECURITY, MF_UNCHECKED);
911
912 if (hMenu)
913 {
914 CheckMenuItem(hMenu, wmId, MF_CHECKED);
915 }
916 }
917
918 // Parse the menu selections:
919 switch (wmId)
920 {
921 case ID_LOG_APPLICATION:
922 QueryEventMessages(lpComputerName, // Use the local computer.
923 EVENT_SOURCE_APPLICATION); // The event log category
924 break;
925
926 case ID_LOG_SYSTEM:
927 QueryEventMessages(lpComputerName, // Use the local computer.
928 EVENT_SOURCE_SYSTEM); // The event log category
929 break;
930
931 case ID_LOG_SECURITY:
932 QueryEventMessages(lpComputerName, // Use the local computer.
933 EVENT_SOURCE_SECURITY); // The event log category
934 break;
935
936 case IDM_REFRESH:
937 Refresh();
938 break;
939
940 case IDM_ABOUT:
941 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
942 break;
943
944 case IDM_HELP:
945 MessageBox(NULL,
946 _TEXT("Help not implemented yet!"),
947 _TEXT("Event Log"),
948 MB_OK | MB_ICONINFORMATION);
949 break;
950
951 case IDM_EXIT:
952 DestroyWindow(hWnd);
953 break;
954
955 default:
956 return DefWindowProc(hWnd, message, wParam, lParam);
957 }
958 break;
959
960 case WM_SIZE:
961 {
962 // Gets the window rectangle
963 GetClientRect(hWnd, &rect);
964
965 // Relocate the listview
966 MoveWindow(hwndListView,
967 0,
968 0,
969 rect.right,
970 rect.bottom - 20,
971 1);
972
973 // Resize the statusbar;
974 SendMessage(hwndStatus, message, wParam, lParam);
975 }
976 break;
977
978 case WM_DESTROY:
979 PostQuitMessage(0);
980 break;
981
982 default:
983 return DefWindowProc(hWnd, message, wParam, lParam);
984 }
985
986 return 0;
987 }
988
989
990 // Message handler for about box.
991 INT_PTR CALLBACK
992 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
993 {
994 UNREFERENCED_PARAMETER(lParam);
995 switch (message)
996 {
997 case WM_INITDIALOG:
998 {
999 return (INT_PTR)TRUE;
1000 }
1001
1002 case WM_COMMAND:
1003 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1004 {
1005 EndDialog(hDlg, LOWORD(wParam));
1006 return (INT_PTR)TRUE;
1007 }
1008 break;
1009 }
1010
1011 return (INT_PTR)FALSE;
1012 }
1013
1014 VOID
1015 DisplayEvent(HWND hDlg)
1016 {
1017 TCHAR szEventType[MAX_PATH];
1018 TCHAR szTime[MAX_PATH];
1019 TCHAR szDate[MAX_PATH];
1020 TCHAR szUser[MAX_PATH];
1021 TCHAR szComputer[MAX_PATH];
1022 TCHAR szSource[MAX_PATH];
1023 TCHAR szCategory[MAX_PATH];
1024 TCHAR szEventID[MAX_PATH];
1025 TCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1026 TCHAR szEventData[MAX_PATH];
1027 BOOL bEventData = FALSE;
1028 LVITEM li;
1029 EVENTLOGRECORD* pevlr;
1030 int iIndex;
1031
1032 // Get index of selected item
1033 iIndex = (int)SendMessage (hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1034
1035 li.mask = LVIF_PARAM;
1036 li.iItem = iIndex;
1037 li.iSubItem = 0;
1038
1039 (void)ListView_GetItem(hwndListView, &li);
1040
1041 pevlr = (EVENTLOGRECORD*)li.lParam;
1042
1043 if (iIndex != -1)
1044 {
1045 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType));
1046 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate));
1047 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime));
1048 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource));
1049 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory));
1050 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID));
1051 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser));
1052 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer));
1053
1054 bEventData = !(pevlr->DataLength == 0);
1055
1056 if (pevlr->DataLength > 0)
1057 {
1058 MultiByteToWideChar(CP_ACP,
1059 0,
1060 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1061 pevlr->DataLength,
1062 szEventData,
1063 MAX_PATH);
1064 }
1065
1066 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1067
1068 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1069 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1070
1071 SetDlgItemText(hDlg, IDC_EVENTDATESTATIC, szDate);
1072 SetDlgItemText(hDlg, IDC_EVENTTIMESTATIC, szTime);
1073 SetDlgItemText(hDlg, IDC_EVENTUSERSTATIC, szUser);
1074 SetDlgItemText(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1075 SetDlgItemText(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1076 SetDlgItemText(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1077 SetDlgItemText(hDlg, IDC_EVENTIDSTATIC, szEventID);
1078 SetDlgItemText(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1079 SetDlgItemText(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1080 SetDlgItemText(hDlg, IDC_EVENTDATAEDIT, szEventData);
1081 }
1082 else
1083 {
1084 MessageBox(NULL,
1085 _TEXT("No Items in ListView"),
1086 _TEXT("Error"),
1087 MB_OK | MB_ICONINFORMATION);
1088 }
1089 }
1090
1091
1092 static
1093 INT_PTR CALLBACK
1094 StatusMessageWindowProc(IN HWND hwndDlg,
1095 IN UINT uMsg,
1096 IN WPARAM wParam,
1097 IN LPARAM lParam)
1098 {
1099 UNREFERENCED_PARAMETER(wParam);
1100
1101 switch (uMsg)
1102 {
1103 case WM_INITDIALOG:
1104 {
1105 return TRUE;
1106 }
1107 }
1108 return FALSE;
1109 }
1110
1111
1112 // Message handler for event details box.
1113 INT_PTR CALLBACK
1114 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1115 {
1116 UNREFERENCED_PARAMETER(lParam);
1117
1118 switch (message)
1119 {
1120 case WM_INITDIALOG:
1121 // Show event info on dialog box
1122 DisplayEvent(hDlg);
1123 return (INT_PTR)TRUE;
1124
1125 case WM_COMMAND:
1126 switch (LOWORD(wParam))
1127 {
1128 case IDOK:
1129 case IDCANCEL:
1130 EndDialog(hDlg, LOWORD(wParam));
1131 return (INT_PTR)TRUE;
1132
1133 case IDPREVIOUS:
1134 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1135
1136 // Show event info on dialog box
1137 DisplayEvent(hDlg);
1138 return (INT_PTR)TRUE;
1139
1140 case IDNEXT:
1141 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1142
1143 // Show event info on dialog box
1144 DisplayEvent(hDlg);
1145 return (INT_PTR)TRUE;
1146
1147 case IDC_BYTESRADIO:
1148 return (INT_PTR)TRUE;
1149
1150 case IDC_WORDRADIO:
1151 return (INT_PTR)TRUE;
1152
1153 case IDHELP:
1154 MessageBox(NULL,
1155 _TEXT("Help not implemented yet!"),
1156 _TEXT("Event Log"),
1157 MB_OK | MB_ICONINFORMATION);
1158 return (INT_PTR)TRUE;
1159
1160 default:
1161 break;
1162 }
1163 break;
1164 }
1165
1166 return (INT_PTR)FALSE;
1167 }