- Replace the check-marks in the protocol menu by radio-bullets because the user...
[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 BOOL
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 FALSE;
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 return TRUE;
691 }
692
693
694 VOID
695 Refresh(VOID)
696 {
697 QueryEventMessages(lpComputerName,
698 lpSourceLogName);
699 }
700
701
702 //
703 // FUNCTION: MyRegisterClass()
704 //
705 // PURPOSE: Registers the window class.
706 //
707 // COMMENTS:
708 //
709 // This function and its usage are only necessary if you want this code
710 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
711 // function that was added to Windows 95. It is important to call this function
712 // so that the application will get 'well formed' small icons associated
713 // with it.
714 //
715 ATOM
716 MyRegisterClass(HINSTANCE hInstance)
717 {
718 WNDCLASSEX wcex;
719
720 wcex.cbSize = sizeof(WNDCLASSEX);
721
722 wcex.style = CS_HREDRAW | CS_VREDRAW;
723 wcex.lpfnWndProc = WndProc;
724 wcex.cbClsExtra = 0;
725 wcex.cbWndExtra = 0;
726 wcex.hInstance = hInstance;
727 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
728 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
729 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
730 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
731 wcex.lpszClassName = szWindowClass;
732 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
733
734 return RegisterClassEx(&wcex);
735 }
736
737
738 //
739 // FUNCTION: InitInstance(HINSTANCE, int)
740 //
741 // PURPOSE: Saves instance handle and creates main window
742 //
743 // COMMENTS:
744 //
745 // In this function, we save the instance handle in a global variable and
746 // create and display the main program window.
747 //
748 BOOL
749 InitInstance(HINSTANCE hInstance,
750 int nCmdShow)
751 {
752 HIMAGELIST hSmall;
753 LVCOLUMN lvc = {0};
754
755 hInst = hInstance; // Store instance handle in our global variable
756
757 hwndMainWindow = CreateWindow(szWindowClass,
758 szTitle,
759 WS_OVERLAPPEDWINDOW,
760 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
761 NULL,
762 NULL,
763 hInstance,
764 NULL);
765 if (!hwndMainWindow)
766 {
767 return FALSE;
768 }
769
770 hwndStatus = CreateWindowEx(0, // no extended styles
771 STATUSCLASSNAME, // status bar
772 _TEXT("Done."), // no text
773 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
774 0, 0, 0, 0, // x, y, cx, cy
775 hwndMainWindow, // parent window
776 (HMENU)100, // window ID
777 hInstance, // instance
778 NULL); // window data
779
780 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
781 // and WS_BORDER to create the normal "sunken" look. Also note that
782 // LVS_EX_ styles cannot be set in CreateWindowEx().
783 hwndListView = CreateWindowEx(WS_EX_CLIENTEDGE,
784 WC_LISTVIEW,
785 _TEXT(""),
786 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
787 0,
788 0,
789 243,
790 200,
791 hwndMainWindow,
792 NULL,
793 hInstance,
794 NULL);
795
796 // After the ListView is created, we can add extended list view styles.
797 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
798
799 // Create the ImageList
800 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
801 GetSystemMetrics(SM_CYSMICON),
802 ILC_MASK,
803 1,
804 1);
805
806 // Add event type icons to ImageList
807 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
808 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
809 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
810
811 // Assign ImageList to List View
812 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
813
814 // Now set up the listview with its columns.
815 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
816 lvc.cx = 90;
817 lvc.pszText = _T("Type");
818 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
819
820 lvc.cx = 70;
821 lvc.pszText = _T("Date");
822 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
823
824 lvc.cx = 70;
825 lvc.pszText = _T("Time");
826 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
827
828 lvc.cx = 150;
829 lvc.pszText = _T("Source");
830 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
831
832 lvc.cx = 100;
833 lvc.pszText = _T("Category");
834 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
835
836 lvc.cx = 60;
837 lvc.pszText = _T("Event");
838 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
839
840 lvc.cx = 120;
841 lvc.pszText = _T("User");
842 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
843
844 lvc.cx = 100;
845 lvc.pszText = _T("Computer");
846 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
847
848 lvc.cx = 0;
849 lvc.pszText = _T("Event Data");
850 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
851
852 ShowWindow(hwndMainWindow, nCmdShow);
853 UpdateWindow(hwndMainWindow);
854
855 QueryEventMessages(lpComputerName, // Use the local computer.
856 EVENT_SOURCE_APPLICATION); // The event log category
857
858 return TRUE;
859 }
860
861
862 //
863 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
864 //
865 // PURPOSE: Processes messages for the main window.
866 //
867 // WM_COMMAND - process the application menu
868 // WM_PAINT - Paint the main window
869 // WM_DESTROY - post a quit message and return
870 //
871 //
872 LRESULT CALLBACK
873 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
874 {
875 RECT rect;
876 NMHDR *hdr;
877
878 switch (message)
879 {
880 case WM_CREATE:
881 CheckMenuRadioItem(GetMenu(hWnd),
882 ID_LOG_APPLICATION,
883 ID_LOG_SYSTEM,
884 ID_LOG_APPLICATION,
885 MF_BYCOMMAND);
886 break;
887
888 case WM_NOTIFY:
889 switch (((LPNMHDR)lParam)->code)
890 {
891 case NM_DBLCLK :
892 hdr = (NMHDR FAR*)lParam;
893 if (hdr->hwndFrom == hwndListView)
894 {
895 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
896
897 if (lpnmitem->iItem != -1)
898 {
899 DialogBox(hInst,
900 MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG),
901 hWnd,
902 EventDetails);
903 }
904 }
905 break;
906 }
907 break;
908
909 case WM_COMMAND:
910 // Parse the menu selections:
911 switch (LOWORD(wParam))
912 {
913 case ID_LOG_APPLICATION:
914 if (QueryEventMessages(lpComputerName, // Use the local computer.
915 EVENT_SOURCE_APPLICATION)) // The event log category
916 {
917 CheckMenuRadioItem(GetMenu(hWnd),
918 ID_LOG_APPLICATION,
919 ID_LOG_SYSTEM,
920 ID_LOG_APPLICATION,
921 MF_BYCOMMAND);
922 }
923 break;
924
925 case ID_LOG_SECURITY:
926 if (QueryEventMessages(lpComputerName, // Use the local computer.
927 EVENT_SOURCE_SECURITY)) // The event log category
928 {
929 CheckMenuRadioItem(GetMenu(hWnd),
930 ID_LOG_APPLICATION,
931 ID_LOG_SYSTEM,
932 ID_LOG_SECURITY,
933 MF_BYCOMMAND);
934 }
935 break;
936
937 case ID_LOG_SYSTEM:
938 if (QueryEventMessages(lpComputerName, // Use the local computer.
939 EVENT_SOURCE_SYSTEM)) // The event log category
940 {
941 CheckMenuRadioItem(GetMenu(hWnd),
942 ID_LOG_APPLICATION,
943 ID_LOG_SYSTEM,
944 ID_LOG_SYSTEM,
945 MF_BYCOMMAND);
946 }
947 break;
948
949 case IDM_REFRESH:
950 Refresh();
951 break;
952
953 case IDM_ABOUT:
954 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
955 break;
956
957 case IDM_HELP:
958 MessageBox(NULL,
959 _TEXT("Help not implemented yet!"),
960 _TEXT("Event Log"),
961 MB_OK | MB_ICONINFORMATION);
962 break;
963
964 case IDM_EXIT:
965 DestroyWindow(hWnd);
966 break;
967
968 default:
969 return DefWindowProc(hWnd, message, wParam, lParam);
970 }
971 break;
972
973 case WM_SIZE:
974 {
975 // Gets the window rectangle
976 GetClientRect(hWnd, &rect);
977
978 // Relocate the listview
979 MoveWindow(hwndListView,
980 0,
981 0,
982 rect.right,
983 rect.bottom - 20,
984 1);
985
986 // Resize the statusbar;
987 SendMessage(hwndStatus, message, wParam, lParam);
988 }
989 break;
990
991 case WM_DESTROY:
992 PostQuitMessage(0);
993 break;
994
995 default:
996 return DefWindowProc(hWnd, message, wParam, lParam);
997 }
998
999 return 0;
1000 }
1001
1002
1003 // Message handler for about box.
1004 INT_PTR CALLBACK
1005 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1006 {
1007 UNREFERENCED_PARAMETER(lParam);
1008 switch (message)
1009 {
1010 case WM_INITDIALOG:
1011 {
1012 return (INT_PTR)TRUE;
1013 }
1014
1015 case WM_COMMAND:
1016 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1017 {
1018 EndDialog(hDlg, LOWORD(wParam));
1019 return (INT_PTR)TRUE;
1020 }
1021 break;
1022 }
1023
1024 return (INT_PTR)FALSE;
1025 }
1026
1027 VOID
1028 DisplayEvent(HWND hDlg)
1029 {
1030 TCHAR szEventType[MAX_PATH];
1031 TCHAR szTime[MAX_PATH];
1032 TCHAR szDate[MAX_PATH];
1033 TCHAR szUser[MAX_PATH];
1034 TCHAR szComputer[MAX_PATH];
1035 TCHAR szSource[MAX_PATH];
1036 TCHAR szCategory[MAX_PATH];
1037 TCHAR szEventID[MAX_PATH];
1038 TCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1039 TCHAR szEventData[MAX_PATH];
1040 BOOL bEventData = FALSE;
1041 LVITEM li;
1042 EVENTLOGRECORD* pevlr;
1043 int iIndex;
1044
1045 // Get index of selected item
1046 iIndex = (int)SendMessage (hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1047
1048 li.mask = LVIF_PARAM;
1049 li.iItem = iIndex;
1050 li.iSubItem = 0;
1051
1052 (void)ListView_GetItem(hwndListView, &li);
1053
1054 pevlr = (EVENTLOGRECORD*)li.lParam;
1055
1056 if (iIndex != -1)
1057 {
1058 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType));
1059 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate));
1060 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime));
1061 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource));
1062 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory));
1063 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID));
1064 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser));
1065 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer));
1066
1067 bEventData = !(pevlr->DataLength == 0);
1068
1069 if (pevlr->DataLength > 0)
1070 {
1071 MultiByteToWideChar(CP_ACP,
1072 0,
1073 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1074 pevlr->DataLength,
1075 szEventData,
1076 MAX_PATH);
1077 }
1078
1079 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1080
1081 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1082 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1083
1084 SetDlgItemText(hDlg, IDC_EVENTDATESTATIC, szDate);
1085 SetDlgItemText(hDlg, IDC_EVENTTIMESTATIC, szTime);
1086 SetDlgItemText(hDlg, IDC_EVENTUSERSTATIC, szUser);
1087 SetDlgItemText(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1088 SetDlgItemText(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1089 SetDlgItemText(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1090 SetDlgItemText(hDlg, IDC_EVENTIDSTATIC, szEventID);
1091 SetDlgItemText(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1092 SetDlgItemText(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1093 SetDlgItemText(hDlg, IDC_EVENTDATAEDIT, szEventData);
1094 }
1095 else
1096 {
1097 MessageBox(NULL,
1098 _TEXT("No Items in ListView"),
1099 _TEXT("Error"),
1100 MB_OK | MB_ICONINFORMATION);
1101 }
1102 }
1103
1104
1105 static
1106 INT_PTR CALLBACK
1107 StatusMessageWindowProc(IN HWND hwndDlg,
1108 IN UINT uMsg,
1109 IN WPARAM wParam,
1110 IN LPARAM lParam)
1111 {
1112 UNREFERENCED_PARAMETER(wParam);
1113
1114 switch (uMsg)
1115 {
1116 case WM_INITDIALOG:
1117 {
1118 return TRUE;
1119 }
1120 }
1121 return FALSE;
1122 }
1123
1124
1125 // Message handler for event details box.
1126 INT_PTR CALLBACK
1127 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1128 {
1129 UNREFERENCED_PARAMETER(lParam);
1130
1131 switch (message)
1132 {
1133 case WM_INITDIALOG:
1134 // Show event info on dialog box
1135 DisplayEvent(hDlg);
1136 return (INT_PTR)TRUE;
1137
1138 case WM_COMMAND:
1139 switch (LOWORD(wParam))
1140 {
1141 case IDOK:
1142 case IDCANCEL:
1143 EndDialog(hDlg, LOWORD(wParam));
1144 return (INT_PTR)TRUE;
1145
1146 case IDPREVIOUS:
1147 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1148
1149 // Show event info on dialog box
1150 DisplayEvent(hDlg);
1151 return (INT_PTR)TRUE;
1152
1153 case IDNEXT:
1154 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1155
1156 // Show event info on dialog box
1157 DisplayEvent(hDlg);
1158 return (INT_PTR)TRUE;
1159
1160 case IDC_BYTESRADIO:
1161 return (INT_PTR)TRUE;
1162
1163 case IDC_WORDRADIO:
1164 return (INT_PTR)TRUE;
1165
1166 case IDHELP:
1167 MessageBox(NULL,
1168 _TEXT("Help not implemented yet!"),
1169 _TEXT("Event Log"),
1170 MB_OK | MB_ICONINFORMATION);
1171 return (INT_PTR)TRUE;
1172
1173 default:
1174 break;
1175 }
1176 break;
1177 }
1178
1179 return (INT_PTR)FALSE;
1180 }