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