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