Replace TABs by Spaces.
[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 LPSTR EVENT_SOURCE_APPLICATION = "Application";
39 static const LPSTR EVENT_SOURCE_SECURITY = "Security";
40 static const LPSTR EVENT_SOURCE_SYSTEM = "System";
41 static const TCHAR szWindowClass[] = _T("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 ";"
47 #define EVENT_MESSAGE_FILE "EventMessageFile"
48 #define EVENT_CATEGORY_MESSAGE_FILE "CategoryMessageFile"
49 #define EVENT_PARAMETER_MESSAGE_FILE "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(LPSTR s)
143 {
144 char *c;
145
146 if ( s != (char *) NULL )
147 {
148 c = s + strlen ( s ) - 1;
149 while ( c >= s && isspace ( *c ) )
150 --c;
151 *++c = '\0';
152 }
153 }
154
155
156 BOOL
157 GetEventMessageFileDLL(IN LPCTSTR lpLogName,
158 IN LPCTSTR SourceName,
159 IN LPCTSTR EntryName,
160 OUT LPSTR 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, _T("\\"));
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((LPSTR)lpMsgBuf);
249
250 // Copy the category name
251 strcpy(CategoryName, (LPCTSTR)lpMsgBuf);
252 }
253 else
254 {
255 strcpy(CategoryName, (LPCTSTR)lpMsgBuf);
256 }
257 }
258 else
259 {
260 strcpy(CategoryName, "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 strcpy(CategoryName, "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 char SourceModuleName[1000];
289 char 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 (strstr(szMessage , "%%"))
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 += strlen(szMessage) + 1;
321 }
322 else
323 {
324 szArguments[i] = szMessage;
325 szMessage += strlen(szMessage) + 1;
326 }
327 }
328
329 szDll = strtok(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 = strtok(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 szArguments) == 0)
353 {
354 // We haven't found the string , get next DLL (if any)
355 szDll = strtok (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((LPSTR)lpMsgBuf);
366
367 // Copy the event text
368 strcpy(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 LPSTR 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, OUT LPSTR pszUser)
427 {
428 PSID lpSid;
429 char szName[1024];
430 char szDomain[1024];
431 SID_NAME_USE peUse;
432 DWORD cbName = 1024;
433 DWORD cbDomain = 1024;
434
435 // Point to the SID.
436 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
437
438 // User SID
439 if (pelr->UserSidLength > 0)
440 {
441 if (LookupAccountSid(NULL,
442 lpSid,
443 szName,
444 &cbName,
445 szDomain,
446 &cbDomain,
447 &peUse))
448 {
449 strcpy(pszUser, szName);
450 return TRUE;
451 }
452 }
453
454 return FALSE;
455 }
456
457
458 static DWORD WINAPI
459 ShowStatusMessageThread(IN LPVOID lpParameter)
460 {
461 HWND *phWnd = (HWND *)lpParameter;
462 HWND hWnd;
463 MSG Msg;
464
465 hWnd = CreateDialogParam(hInst,
466 MAKEINTRESOURCE(IDD_PROGRESSBOX),
467 GetDesktopWindow(),
468 StatusMessageWindowProc,
469 (LPARAM)NULL);
470 if (!hWnd)
471 return 0;
472
473 *phWnd = hWnd;
474
475 ShowWindow(hWnd, SW_SHOW);
476
477 /* Message loop for the Status window */
478 while (GetMessage(&Msg, NULL, 0, 0))
479 {
480 TranslateMessage(&Msg);
481 DispatchMessage(&Msg);
482 }
483
484 return 0;
485 }
486
487
488 VOID
489 QueryEventMessages(LPTSTR lpMachineName,
490 LPTSTR lpLogName)
491 {
492 HWND hwndDlg;
493 HANDLE hEventLog;
494 EVENTLOGRECORD *pevlr;
495 BYTE bBuffer[MAX_PATH];
496 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords, dwCurrentRecord = 1, dwRecordsToRead = 0, dwFlags;
497 LPSTR lpSourceName;
498 LPSTR lpComputerName;
499 LPSTR lpEventStr;
500 LPSTR lpData;
501 BOOL bResult = TRUE; // Read succeeded.
502
503 char szWindowTitle[MAX_PATH];
504 char szStatusText[MAX_PATH];
505 char szLocalDate[MAX_PATH];
506 char szLocalTime[MAX_PATH];
507 char szEventID[MAX_PATH];
508 char szEventTypeText[MAX_PATH];
509 char szCategoryID[MAX_PATH];
510 char szUsername[MAX_PATH];
511 char szEventText[EVENT_MESSAGE_FILE_BUFFER];
512 char szCategory[MAX_PATH];
513
514 SYSTEMTIME time;
515 LVITEM lviEventItem;
516
517 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
518
519 lpSourceLogName = lpLogName;
520 lpComputerName = lpMachineName;
521
522 // Open the event log.
523 hEventLog = OpenEventLog(lpMachineName,
524 lpLogName);
525 if (hEventLog == NULL)
526 {
527 MessageBox(NULL,
528 _TEXT("Could not open the event log."),
529 _TEXT("Event Log"),
530 MB_OK | MB_ICONINFORMATION);
531 return;
532 }
533
534 // Disable listview redraw
535 SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0);
536
537 // Clear the list view
538 (void)ListView_DeleteAllItems (hwndListView);
539
540 // Initialize the event record buffer.
541 pevlr = (EVENTLOGRECORD *)&bBuffer;
542
543 // Get the record number of the oldest event log record.
544 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
545
546 // Get the total number of event log records.
547 GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords);
548
549 //If we have at least 1000 records show the waiting dialog
550 if (dwTotalRecords > 1000)
551 {
552 CreateThread(NULL,
553 0,
554 ShowStatusMessageThread,
555 (LPVOID)&hwndDlg,
556 0,
557 NULL);
558 }
559
560 while (dwCurrentRecord < dwTotalRecords)
561 {
562 pevlr = (EVENTLOGRECORD*)malloc(MAX_PATH);
563
564 bResult = ReadEventLog(hEventLog, // Event log handle
565 dwFlags, // Sequential read
566 0, // Ignored for sequential read
567 pevlr, // Pointer to buffer
568 MAX_PATH, // Size of buffer
569 &dwRead, // Number of bytes read
570 &dwNeeded); // Bytes in the next record
571 if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
572 {
573 pevlr = (EVENTLOGRECORD*)malloc (dwNeeded);
574
575 ReadEventLog(hEventLog, // event log handle
576 dwFlags, // read flags
577 0, // offset; default is 0
578 pevlr, // pointer to buffer
579 dwNeeded, // size of buffer
580 &dwRead, // number of bytes read
581 &dwNeeded); // bytes in next record
582 }
583
584 while (dwRead > 0)
585 {
586 strcpy(szUsername , "N/A");
587 strcpy(szEventText , "N/A");
588 strcpy(szCategory , "None");
589
590 // Get the event source name.
591 lpSourceName = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
592
593 // Get the computer name
594 lpComputerName = (LPSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + lstrlen(lpSourceName) + 1);
595
596 // This ist the data section of the current event
597 lpData = (LPSTR)((LPBYTE)pevlr + pevlr->DataOffset);
598
599 // This is the text of the current event
600 lpEventStr = (LPSTR)((LPBYTE) pevlr + pevlr->StringOffset);
601
602 // Compute the event type
603 EventTimeToSystemTime(pevlr->TimeWritten, &time);
604
605 // Get the username that generated the event
606 GetEventUserName(pevlr, szUsername);
607
608 GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, MAX_PATH);
609 GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, szLocalTime, MAX_PATH);
610
611 GetEventType(pevlr->EventType, szEventTypeText);
612 GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory);
613
614 wsprintf(szEventID, "%u", (DWORD)(pevlr->EventID & 0xFFFF));
615 wsprintf(szCategoryID, "%u", (DWORD)(pevlr->EventCategory));
616
617 lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
618 lviEventItem.iItem = 0;
619 lviEventItem.iSubItem = 0;
620 lviEventItem.lParam = (LPARAM)pevlr;
621 lviEventItem.pszText = szEventTypeText;
622
623 switch (pevlr->EventType)
624 {
625 case EVENTLOG_ERROR_TYPE:
626 lviEventItem.iImage = 2;
627 break;
628
629 case EVENTLOG_AUDIT_FAILURE:
630 lviEventItem.iImage = 2;
631 break;
632
633 case EVENTLOG_WARNING_TYPE:
634 lviEventItem.iImage = 1;
635 break;
636
637 case EVENTLOG_INFORMATION_TYPE:
638 lviEventItem.iImage = 0;
639 break;
640
641 case EVENTLOG_AUDIT_SUCCESS:
642 lviEventItem.iImage = 0;
643 break;
644
645 case EVENTLOG_SUCCESS:
646 lviEventItem.iImage = 0;
647 break;
648 }
649
650 lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem);
651
652 ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate);
653 ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime);
654 ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName);
655 ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory);
656 ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID);
657 ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername); //User
658 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer
659 ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, lpData); //Event Text
660
661 dwRead -= pevlr->Length;
662 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
663 }
664
665 dwRecordsToRead--;
666 dwCurrentRecord++;
667
668 pevlr = (EVENTLOGRECORD *)&bBuffer;
669 }
670
671 // All events loaded
672 EndDialog(hwndDlg, 0);
673
674 wsprintf(szWindowTitle, "%s - %s Log on \\\\%s", szTitle , lpLogName , lpComputerName);
675 wsprintf(szStatusText, "%s has %d event(s)", lpLogName , dwTotalRecords);
676
677 // Update the status bar
678 SendMessage(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
679
680 // Set the window title
681 SetWindowText(hwndMainWindow, szWindowTitle);
682
683 // Resume list view redraw
684 SendMessage(hwndListView, WM_SETREDRAW, TRUE, 0);
685
686 // Close the event log.
687 CloseEventLog(hEventLog);
688 }
689
690
691 VOID
692 Refresh(VOID)
693 {
694 QueryEventMessages(lpComputerName,
695 lpSourceLogName);
696 }
697
698
699 //
700 // FUNCTION: MyRegisterClass()
701 //
702 // PURPOSE: Registers the window class.
703 //
704 // COMMENTS:
705 //
706 // This function and its usage are only necessary if you want this code
707 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
708 // function that was added to Windows 95. It is important to call this function
709 // so that the application will get 'well formed' small icons associated
710 // with it.
711 //
712 ATOM
713 MyRegisterClass(HINSTANCE hInstance)
714 {
715 WNDCLASSEX wcex;
716
717 wcex.cbSize = sizeof(WNDCLASSEX);
718
719 wcex.style = CS_HREDRAW | CS_VREDRAW;
720 wcex.lpfnWndProc = WndProc;
721 wcex.cbClsExtra = 0;
722 wcex.cbWndExtra = 0;
723 wcex.hInstance = hInstance;
724 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
725 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
726 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
727 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
728 wcex.lpszClassName = szWindowClass;
729 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
730
731 return RegisterClassEx(&wcex);
732 }
733
734
735 //
736 // FUNCTION: InitInstance(HINSTANCE, int)
737 //
738 // PURPOSE: Saves instance handle and creates main window
739 //
740 // COMMENTS:
741 //
742 // In this function, we save the instance handle in a global variable and
743 // create and display the main program window.
744 //
745 BOOL
746 InitInstance(HINSTANCE hInstance,
747 int nCmdShow)
748 {
749 HIMAGELIST hSmall;
750 LVCOLUMN lvc = {0};
751
752 hInst = hInstance; // Store instance handle in our global variable
753
754 hwndMainWindow = CreateWindow(szWindowClass,
755 szTitle,
756 WS_OVERLAPPEDWINDOW,
757 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
758 NULL,
759 NULL,
760 hInstance,
761 NULL);
762 if (!hwndMainWindow)
763 {
764 return FALSE;
765 }
766
767 hwndStatus = CreateWindowEx(0, // no extended styles
768 STATUSCLASSNAME, // status bar
769 "Done.", // no text
770 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
771 0, 0, 0, 0, // x, y, cx, cy
772 hwndMainWindow, // parent window
773 (HMENU)100, // window ID
774 hInstance, // instance
775 NULL); // window data
776
777 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
778 // and WS_BORDER to create the normal "sunken" look. Also note that
779 // LVS_EX_ styles cannot be set in CreateWindowEx().
780 hwndListView = CreateWindowEx(WS_EX_CLIENTEDGE,
781 WC_LISTVIEW,
782 _T(""),
783 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
784 0,
785 0,
786 243,
787 200,
788 hwndMainWindow,
789 NULL,
790 hInstance,
791 NULL);
792
793 // After the ListView is created, we can add extended list view styles.
794 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
795
796 // Create the ImageList
797 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
798 GetSystemMetrics(SM_CYSMICON),
799 ILC_MASK,
800 1,
801 1);
802
803 // Add event type icons to ImageList
804 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
805 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
806 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
807
808 // Assign ImageList to List View
809 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
810
811 // Now set up the listview with its columns.
812 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
813 lvc.cx = 90;
814 lvc.pszText = _T("Type");
815 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
816
817 lvc.cx = 70;
818 lvc.pszText = _T("Date");
819 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
820
821 lvc.cx = 70;
822 lvc.pszText = _T("Time");
823 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
824
825 lvc.cx = 150;
826 lvc.pszText = _T("Source");
827 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
828
829 lvc.cx = 100;
830 lvc.pszText = _T("Category");
831 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
832
833 lvc.cx = 60;
834 lvc.pszText = _T("Event");
835 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
836
837 lvc.cx = 120;
838 lvc.pszText = _T("User");
839 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
840
841 lvc.cx = 100;
842 lvc.pszText = _T("Computer");
843 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
844
845 lvc.cx = 0;
846 lvc.pszText = _T("Event Data");
847 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
848
849 ShowWindow(hwndMainWindow, nCmdShow);
850 UpdateWindow(hwndMainWindow);
851
852 QueryEventMessages(lpComputerName, // Use the local computer.
853 EVENT_SOURCE_APPLICATION); // The event log category
854
855 return TRUE;
856 }
857
858
859 //
860 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
861 //
862 // PURPOSE: Processes messages for the main window.
863 //
864 // WM_COMMAND - process the application menu
865 // WM_PAINT - Paint the main window
866 // WM_DESTROY - post a quit message and return
867 //
868 //
869 LRESULT CALLBACK
870 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
871 {
872 int wmId, wmEvent;
873 RECT rect;
874 NMHDR *hdr;
875 HMENU hMenu;
876
877 switch (message)
878 {
879 case WM_NOTIFY:
880 switch (((LPNMHDR)lParam)->code)
881 {
882 case NM_DBLCLK :
883 hdr = (NMHDR FAR*)lParam;
884 if (hdr->hwndFrom == hwndListView)
885 {
886 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
887
888 if (lpnmitem->iItem != -1)
889 {
890 DialogBox(hInst, MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG), hWnd, EventDetails);
891 }
892 }
893 break;
894 }
895 break;
896
897 case WM_COMMAND:
898 wmId = LOWORD(wParam);
899 wmEvent = HIWORD(wParam);
900
901 if ((wmId == ID_LOG_APPLICATION) ||
902 (wmId == ID_LOG_SYSTEM) ||
903 (wmId == ID_LOG_SECURITY))
904 {
905 hMenu = GetMenu(hWnd); // get the menu handle. Use it below
906
907 CheckMenuItem(hMenu, ID_LOG_APPLICATION, MF_UNCHECKED);
908 CheckMenuItem(hMenu, ID_LOG_SYSTEM, MF_UNCHECKED);
909 CheckMenuItem (hMenu, ID_LOG_SECURITY, MF_UNCHECKED);
910
911 if (hMenu)
912 {
913 CheckMenuItem(hMenu, wmId, MF_CHECKED);
914 }
915 }
916
917 // Parse the menu selections:
918 switch (wmId)
919 {
920 case ID_LOG_APPLICATION:
921 QueryEventMessages(lpComputerName, // Use the local computer.
922 EVENT_SOURCE_APPLICATION); // The event log category
923 break;
924
925 case ID_LOG_SYSTEM:
926 QueryEventMessages(lpComputerName, // Use the local computer.
927 EVENT_SOURCE_SYSTEM); // The event log category
928 break;
929
930 case ID_LOG_SECURITY:
931 QueryEventMessages(lpComputerName, // Use the local computer.
932 EVENT_SOURCE_SECURITY); // The event log category
933 break;
934
935 case IDM_REFRESH:
936 Refresh();
937 break;
938
939 case IDM_ABOUT:
940 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
941 break;
942
943 case IDM_HELP:
944 MessageBox(NULL,
945 _TEXT("Help not implemented yet!"),
946 _TEXT("Event Log"),
947 MB_OK | MB_ICONINFORMATION);
948 break;
949
950 case IDM_EXIT:
951 DestroyWindow(hWnd);
952 break;
953
954 default:
955 return DefWindowProc(hWnd, message, wParam, lParam);
956 }
957 break;
958
959 case WM_SIZE:
960 {
961 // Gets the window rectangle
962 GetClientRect(hWnd, &rect);
963
964 // Relocate the listview
965 MoveWindow(hwndListView,
966 0,
967 0,
968 rect.right,
969 rect.bottom - 20,
970 1);
971
972 // Resize the statusbar;
973 SendMessage(hwndStatus, message, wParam, lParam);
974 }
975 break;
976
977 case WM_DESTROY:
978 PostQuitMessage(0);
979 break;
980
981 default:
982 return DefWindowProc(hWnd, message, wParam, lParam);
983 }
984
985 return 0;
986 }
987
988
989 // Message handler for about box.
990 INT_PTR CALLBACK
991 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
992 {
993 UNREFERENCED_PARAMETER(lParam);
994 switch (message)
995 {
996 case WM_INITDIALOG:
997 {
998 return (INT_PTR)TRUE;
999 }
1000
1001 case WM_COMMAND:
1002 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1003 {
1004 EndDialog(hDlg, LOWORD(wParam));
1005 return (INT_PTR)TRUE;
1006 }
1007 break;
1008 }
1009
1010 return (INT_PTR)FALSE;
1011 }
1012
1013 VOID
1014 DisplayEvent(HWND hDlg)
1015 {
1016 char szEventType[MAX_PATH];
1017 char szTime[MAX_PATH];
1018 char szDate[MAX_PATH];
1019 char szUser[MAX_PATH];
1020 char szComputer[MAX_PATH];
1021 char szSource[MAX_PATH];
1022 char szCategory[MAX_PATH];
1023 char szEventID[MAX_PATH];
1024 char szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1025 char szEventData[MAX_PATH];
1026 BOOL bEventData = FALSE;
1027 LVITEM li;
1028 EVENTLOGRECORD* pevlr;
1029 int iIndex;
1030
1031 // Get index of selected item
1032 iIndex = (int)SendMessage (hwndListView ,LVM_GETNEXTITEM, -1 , LVNI_SELECTED | LVNI_FOCUSED);
1033
1034 li.mask = LVIF_PARAM;
1035 li.iItem = iIndex;
1036 li.iSubItem = 0;
1037
1038 (void)ListView_GetItem(hwndListView, &li);
1039
1040 pevlr = (EVENTLOGRECORD*)li.lParam;
1041
1042 if (iIndex != -1)
1043 {
1044 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType));
1045 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate));
1046 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime));
1047 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource));
1048 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory));
1049 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID));
1050 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser));
1051 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer));
1052 ListView_GetItemText(hwndListView, iIndex, 8, szEventData, sizeof(szEventData));
1053
1054 bEventData = !(strlen(szEventData) == 0);
1055
1056 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1057
1058 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1059 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1060
1061 SetDlgItemText(hDlg, IDC_EVENTDATESTATIC, szDate);
1062 SetDlgItemText(hDlg, IDC_EVENTTIMESTATIC, szTime);
1063 SetDlgItemText(hDlg, IDC_EVENTUSERSTATIC, szUser);
1064 SetDlgItemText(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1065 SetDlgItemText(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1066 SetDlgItemText(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1067 SetDlgItemText(hDlg, IDC_EVENTIDSTATIC, szEventID);
1068 SetDlgItemText(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1069 SetDlgItemText(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1070 SetDlgItemText(hDlg, IDC_EVENTDATAEDIT, szEventData);
1071 }
1072 else
1073 {
1074 MessageBox(NULL,
1075 "No Items in ListView",
1076 "Error",
1077 MB_OK | MB_ICONINFORMATION);
1078 }
1079 }
1080
1081
1082 static
1083 INT_PTR CALLBACK
1084 StatusMessageWindowProc(IN HWND hwndDlg,
1085 IN UINT uMsg,
1086 IN WPARAM wParam,
1087 IN LPARAM lParam)
1088 {
1089 UNREFERENCED_PARAMETER(wParam);
1090
1091 switch (uMsg)
1092 {
1093 case WM_INITDIALOG:
1094 {
1095 return TRUE;
1096 }
1097 }
1098 return FALSE;
1099 }
1100
1101
1102 // Message handler for event details box.
1103 INT_PTR CALLBACK
1104 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1105 {
1106 UNREFERENCED_PARAMETER(lParam);
1107
1108 switch (message)
1109 {
1110 case WM_INITDIALOG:
1111 // Show event info on dialog box
1112 DisplayEvent(hDlg);
1113 return (INT_PTR)TRUE;
1114
1115 case WM_COMMAND:
1116 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1117 {
1118 EndDialog(hDlg, LOWORD(wParam));
1119 return (INT_PTR)TRUE;
1120 }
1121
1122 if (LOWORD(wParam) == IDPREVIOUS)
1123 {
1124 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1125
1126 // Show event info on dialog box
1127 DisplayEvent(hDlg);
1128 return (INT_PTR)TRUE;
1129 }
1130
1131 if (LOWORD(wParam) == IDNEXT)
1132 {
1133 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1134
1135 // Show event info on dialog box
1136 DisplayEvent(hDlg);
1137 return (INT_PTR)TRUE;
1138 }
1139
1140 if (LOWORD(wParam) == IDC_BYTESRADIO)
1141 {
1142 return (INT_PTR)TRUE;
1143 }
1144
1145 if (LOWORD(wParam) == IDC_WORDRADIO)
1146 {
1147 return (INT_PTR)TRUE;
1148 }
1149
1150 if (LOWORD(wParam) == IDHELP)
1151 {
1152 MessageBox(NULL,
1153 _TEXT("Help not implemented yet!"),
1154 _TEXT("Event Log"),
1155 MB_OK | MB_ICONINFORMATION);
1156 return (INT_PTR)TRUE;
1157 }
1158 break;
1159 }
1160
1161 return (INT_PTR)FALSE;
1162 }