[EVENTVWR]
[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 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 if (lpMsgBuf)
265 {
266 /* Trim the string */
267 TrimNulls((LPWSTR)lpMsgBuf);
268
269 /* Copy the category name */
270 wcscpy(CategoryName, (LPCWSTR)lpMsgBuf);
271 }
272 else
273 {
274 wcscpy(CategoryName, (LPCWSTR)lpMsgBuf);
275 }
276 }
277 else
278 {
279 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
280 }
281
282 if (hLibrary != NULL)
283 FreeLibrary(hLibrary);
284
285 /* Free the buffer allocated by FormatMessage */
286 if (lpMsgBuf)
287 LocalFree(lpMsgBuf);
288
289 return TRUE;
290 }
291 }
292
293 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
294
295 return FALSE;
296 }
297
298
299 BOOL
300 GetEventMessage(IN LPCWSTR KeyName,
301 IN LPCWSTR SourceName,
302 IN EVENTLOGRECORD *pevlr,
303 OUT LPWSTR EventText)
304 {
305 DWORD i;
306 HANDLE hLibrary = NULL;
307 WCHAR SourceModuleName[1000];
308 WCHAR ParameterModuleName[1000];
309 LPWSTR lpMsgBuf = NULL;
310 WCHAR szStringIDNotFound[MAX_LOADSTRING];
311 LPWSTR szDll;
312 LPWSTR szMessage;
313 LPWSTR *szArguments;
314 BOOL bDone = FALSE;
315
316 /* TODO : GetEventMessageFileDLL can return a comma separated list of DLLs */
317 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_MESSAGE_FILE, SourceModuleName))
318 {
319 /* Get the event message */
320 szMessage = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
321
322 /* Allocate space for parameters */
323 szArguments = malloc(sizeof(LPVOID) * pevlr->NumStrings);
324 if (!szArguments)
325 {
326 return FALSE;
327 }
328
329 for (i = 0; i < pevlr->NumStrings ; i++)
330 {
331 if (wcsstr(szMessage , L"%%"))
332 {
333 if (GetEventMessageFileDLL(KeyName, SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
334 {
335 /* Not yet support for reading messages from parameter message DLL */
336 }
337 }
338
339 szArguments[i] = szMessage;
340 szMessage += wcslen(szMessage) + 1;
341 }
342
343 szDll = wcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
344 while ((szDll != NULL) && (!bDone))
345 {
346 hLibrary = LoadLibraryExW(szDll,
347 NULL,
348 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
349 if (hLibrary == NULL)
350 {
351 /* The DLL could not be loaded try the next one (if any) */
352 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
353 }
354 else
355 {
356 /* Retrieve the message string. */
357 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
358 FORMAT_MESSAGE_ALLOCATE_BUFFER |
359 FORMAT_MESSAGE_FROM_HMODULE |
360 FORMAT_MESSAGE_ARGUMENT_ARRAY,
361 hLibrary,
362 pevlr->EventID,
363 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
364 (LPWSTR)&lpMsgBuf,
365 0,
366 (va_list*)szArguments) == 0)
367 {
368 /* We haven't found the string , get next DLL (if any) */
369 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
370 }
371 else
372 {
373 if (lpMsgBuf)
374 {
375 /* The ID was found and the message was formated */
376 bDone = TRUE;
377
378 /* Trim the string */
379 TrimNulls((LPWSTR)lpMsgBuf);
380
381 /* Copy the event text */
382 wcscpy(EventText ,lpMsgBuf);
383 }
384 }
385
386 FreeLibrary(hLibrary);
387 }
388 }
389
390 if (!bDone)
391 {
392 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
393 swprintf(EventText, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
394 }
395
396 free(szArguments);
397
398 /* No more dlls to try, return result */
399 return bDone;
400 }
401
402 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
403 swprintf(EventText, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
404
405 return FALSE;
406 }
407
408
409 VOID
410 GetEventType(IN WORD dwEventType,
411 OUT LPWSTR eventTypeText)
412 {
413 switch (dwEventType)
414 {
415 case EVENTLOG_ERROR_TYPE:
416 LoadStringW(hInst, IDS_EVENTLOG_ERROR_TYPE, eventTypeText, MAX_LOADSTRING);
417 break;
418 case EVENTLOG_WARNING_TYPE:
419 LoadStringW(hInst, IDS_EVENTLOG_WARNING_TYPE, eventTypeText, MAX_LOADSTRING);
420 break;
421 case EVENTLOG_INFORMATION_TYPE:
422 LoadStringW(hInst, IDS_EVENTLOG_INFORMATION_TYPE, eventTypeText, MAX_LOADSTRING);
423 break;
424 case EVENTLOG_AUDIT_SUCCESS:
425 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_SUCCESS, eventTypeText, MAX_LOADSTRING);
426 break;
427 case EVENTLOG_AUDIT_FAILURE:
428 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_FAILURE, eventTypeText, MAX_LOADSTRING);
429 break;
430 case EVENTLOG_SUCCESS:
431 LoadStringW(hInst, IDS_EVENTLOG_SUCCESS, eventTypeText, MAX_LOADSTRING);
432 break;
433 default:
434 LoadStringW(hInst, IDS_EVENTLOG_UNKNOWN_TYPE, eventTypeText, MAX_LOADSTRING);
435 break;
436 }
437 }
438
439 BOOL
440 GetEventUserName(EVENTLOGRECORD *pelr,
441 OUT LPWSTR pszUser)
442 {
443 PSID lpSid;
444 WCHAR szName[1024];
445 WCHAR szDomain[1024];
446 SID_NAME_USE peUse;
447 DWORD cbName = 1024;
448 DWORD cbDomain = 1024;
449
450 /* Point to the SID. */
451 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
452
453 /* User SID */
454 if (pelr->UserSidLength > 0)
455 {
456 if (LookupAccountSidW(NULL,
457 lpSid,
458 szName,
459 &cbName,
460 szDomain,
461 &cbDomain,
462 &peUse))
463 {
464 wcscpy(pszUser, szName);
465 return TRUE;
466 }
467 }
468
469 return FALSE;
470 }
471
472
473 static DWORD WINAPI
474 ShowStatusMessageThread(IN LPVOID lpParameter)
475 {
476 HWND *phWnd = (HWND *)lpParameter;
477 HWND hWnd;
478 MSG Msg;
479
480 hWnd = CreateDialogParam(hInst,
481 MAKEINTRESOURCE(IDD_PROGRESSBOX),
482 GetDesktopWindow(),
483 StatusMessageWindowProc,
484 (LPARAM)NULL);
485 if (!hWnd)
486 return 0;
487
488 *phWnd = hWnd;
489
490 ShowWindow(hWnd, SW_SHOW);
491
492 /* Message loop for the Status window */
493 while (GetMessage(&Msg, NULL, 0, 0))
494 {
495 TranslateMessage(&Msg);
496 DispatchMessage(&Msg);
497 }
498
499 return 0;
500 }
501
502
503 BOOL
504 QueryEventMessages(LPWSTR lpMachineName,
505 LPWSTR lpLogName)
506 {
507 HWND hwndDlg;
508 HANDLE hEventLog;
509 EVENTLOGRECORD *pevlr;
510 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords = 0, dwCurrentRecord = 0, dwRecordsToRead = 0, dwFlags, dwMaxLength;
511 LPWSTR lpSourceName;
512 LPWSTR lpComputerName;
513 LPSTR lpData;
514 BOOL bResult = TRUE; /* Read succeeded. */
515 int i;
516
517 WCHAR szWindowTitle[MAX_PATH];
518 WCHAR szStatusText[MAX_PATH];
519 WCHAR szLocalDate[MAX_PATH];
520 WCHAR szLocalTime[MAX_PATH];
521 WCHAR szEventID[MAX_PATH];
522 WCHAR szEventTypeText[MAX_PATH];
523 WCHAR szCategoryID[MAX_PATH];
524 WCHAR szUsername[MAX_PATH];
525 WCHAR szEventText[EVENT_MESSAGE_FILE_BUFFER];
526 WCHAR szCategory[MAX_PATH];
527 WCHAR szData[MAX_PATH];
528
529 SYSTEMTIME time;
530 LVITEMW lviEventItem;
531
532 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
533
534 lpSourceLogName = lpLogName;
535 lpComputerName = lpMachineName;
536
537 /* Open the event log. */
538 hEventLog = OpenEventLogW(lpMachineName,
539 lpLogName);
540 if (hEventLog == NULL)
541 {
542 MessageBoxW(NULL,
543 L"Could not open the event log.",
544 L"Event Log",
545 MB_OK | MB_ICONINFORMATION);
546 return FALSE;
547 }
548
549 /* Disable listview redraw */
550 SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0);
551
552 /* Clear the list view */
553 (void)ListView_DeleteAllItems (hwndListView);
554 FreeRecords();
555
556 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
557
558 /* Get the total number of event log records. */
559 GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords);
560 g_TotalRecords = dwTotalRecords;
561
562 g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(PVOID));
563
564 /* If we have at least 1000 records show the waiting dialog */
565 if (dwTotalRecords > 1000)
566 {
567 CloseHandle(CreateThread(NULL,
568 0,
569 ShowStatusMessageThread,
570 (LPVOID)&hwndDlg,
571 0,
572 NULL));
573 }
574
575 while (dwCurrentRecord < dwTotalRecords)
576 {
577 pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD) * dwTotalRecords);
578 g_RecordPtrs[dwCurrentRecord] = pevlr;
579
580 bResult = ReadEventLog(hEventLog, // Event log handle
581 dwFlags, // Sequential read
582 0, // Ignored for sequential read
583 pevlr, // Pointer to buffer
584 sizeof(EVENTLOGRECORD), // Size of buffer
585 &dwRead, // Number of bytes read
586 &dwNeeded); // Bytes in the next record
587 if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
588 {
589 HeapFree(GetProcessHeap(), 0, pevlr);
590 pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded);
591 g_RecordPtrs[dwCurrentRecord] = pevlr;
592
593 ReadEventLogW(hEventLog, // event log handle
594 dwFlags, // read flags
595 0, // offset; default is 0
596 pevlr, // pointer to buffer
597 dwNeeded, // size of buffer
598 &dwRead, // number of bytes read
599 &dwNeeded); // bytes in next record
600 }
601
602 while (dwRead > 0)
603 {
604 LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, MAX_PATH);
605 LoadStringW(hInst, IDS_NOT_AVAILABLE, szEventText, MAX_PATH);
606 LoadStringW(hInst, IDS_NONE, szCategory, MAX_PATH);
607
608 // Get the event source name.
609 lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
610
611 // Get the computer name
612 lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR));
613
614 // This ist the data section of the current event
615 lpData = (LPSTR)((LPBYTE)pevlr + pevlr->DataOffset);
616
617 // Compute the event type
618 EventTimeToSystemTime(pevlr->TimeWritten, &time);
619
620 // Get the username that generated the event
621 GetEventUserName(pevlr, szUsername);
622
623 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, MAX_PATH);
624 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, szLocalTime, MAX_PATH);
625
626 GetEventType(pevlr->EventType, szEventTypeText);
627 GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory);
628
629 swprintf(szEventID, L"%u", (pevlr->EventID & 0xFFFF));
630 swprintf(szCategoryID, L"%u", pevlr->EventCategory);
631
632 lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
633 lviEventItem.iItem = 0;
634 lviEventItem.iSubItem = 0;
635 lviEventItem.lParam = (LPARAM)pevlr;
636 lviEventItem.pszText = szEventTypeText;
637
638 switch (pevlr->EventType)
639 {
640 case EVENTLOG_ERROR_TYPE:
641 lviEventItem.iImage = 2;
642 break;
643
644 case EVENTLOG_AUDIT_FAILURE:
645 lviEventItem.iImage = 2;
646 break;
647
648 case EVENTLOG_WARNING_TYPE:
649 lviEventItem.iImage = 1;
650 break;
651
652 case EVENTLOG_INFORMATION_TYPE:
653 lviEventItem.iImage = 0;
654 break;
655
656 case EVENTLOG_AUDIT_SUCCESS:
657 lviEventItem.iImage = 0;
658 break;
659
660 case EVENTLOG_SUCCESS:
661 lviEventItem.iImage = 0;
662 break;
663 }
664
665 lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem);
666
667 ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate);
668 ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime);
669 ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName);
670 ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory);
671 ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID);
672 ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername); //User
673 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer
674 MultiByteToWideChar(CP_ACP,
675 0,
676 lpData,
677 pevlr->DataLength,
678 szData,
679 MAX_PATH);
680 ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, szData); //Event Text
681
682 dwRead -= pevlr->Length;
683 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
684 }
685
686 dwRecordsToRead--;
687 dwCurrentRecord++;
688 }
689
690 // All events loaded
691 EndDialog(hwndDlg, 0);
692
693
694 i = swprintf(szWindowTitle, szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */
695 /* lpComputerName can be NULL here if no records was read */
696 dwMaxLength = sizeof(szWindowTitle) / sizeof(WCHAR) - i;
697 if(!lpComputerName)
698 GetComputerNameW(szWindowTitle+i, &dwMaxLength);
699 else
700 _snwprintf(szWindowTitle+i, dwMaxLength, L"%s", lpComputerName);
701
702 swprintf(szStatusText, szStatusBarTemplate, lpLogName, dwTotalRecords);
703
704 // Update the status bar
705 SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
706
707 // Set the window title
708 SetWindowTextW(hwndMainWindow, szWindowTitle);
709
710 // Resume list view redraw
711 SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
712
713 // Close the event log.
714 CloseEventLog(hEventLog);
715
716 return TRUE;
717 }
718
719
720 VOID
721 Refresh(VOID)
722 {
723 QueryEventMessages(lpComputerName,
724 lpSourceLogName);
725 }
726
727
728 //
729 // FUNCTION: MyRegisterClass()
730 //
731 // PURPOSE: Registers the window class.
732 //
733 // COMMENTS:
734 //
735 // This function and its usage are only necessary if you want this code
736 // to be compatible with Win32 systems prior to the 'RegisterClassEx'
737 // function that was added to Windows 95. It is important to call this function
738 // so that the application will get 'well formed' small icons associated
739 // with it.
740 //
741 ATOM
742 MyRegisterClass(HINSTANCE hInstance)
743 {
744 WNDCLASSEXW wcex;
745
746 wcex.cbSize = sizeof(WNDCLASSEX);
747
748 wcex.style = 0;
749 wcex.lpfnWndProc = WndProc;
750 wcex.cbClsExtra = 0;
751 wcex.cbWndExtra = 0;
752 wcex.hInstance = hInstance;
753 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
754 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
755 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
756 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
757 wcex.lpszClassName = szWindowClass;
758 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
759
760 return RegisterClassExW(&wcex);
761 }
762
763
764 //
765 // FUNCTION: InitInstance(HINSTANCE, int)
766 //
767 // PURPOSE: Saves instance handle and creates main window
768 //
769 // COMMENTS:
770 //
771 // In this function, we save the instance handle in a global variable and
772 // create and display the main program window.
773 //
774 BOOL
775 InitInstance(HINSTANCE hInstance,
776 int nCmdShow)
777 {
778 HIMAGELIST hSmall;
779 LVCOLUMNW lvc = {0};
780 WCHAR szTemp[256];
781
782 hInst = hInstance; // Store instance handle in our global variable
783
784 hwndMainWindow = CreateWindowW(szWindowClass,
785 szTitle,
786 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
787 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
788 NULL,
789 NULL,
790 hInstance,
791 NULL);
792 if (!hwndMainWindow)
793 {
794 return FALSE;
795 }
796
797 hwndStatus = CreateWindowExW(0, // no extended styles
798 STATUSCLASSNAMEW, // status bar
799 L"Done.", // no text
800 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
801 0, 0, 0, 0, // x, y, cx, cy
802 hwndMainWindow, // parent window
803 (HMENU)100, // window ID
804 hInstance, // instance
805 NULL); // window data
806
807 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
808 // and WS_BORDER to create the normal "sunken" look. Also note that
809 // LVS_EX_ styles cannot be set in CreateWindowEx().
810 hwndListView = CreateWindowExW(WS_EX_CLIENTEDGE,
811 WC_LISTVIEWW,
812 L"",
813 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
814 0,
815 0,
816 243,
817 200,
818 hwndMainWindow,
819 NULL,
820 hInstance,
821 NULL);
822
823 // After the ListView is created, we can add extended list view styles.
824 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
825
826 // Create the ImageList
827 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
828 GetSystemMetrics(SM_CYSMICON),
829 ILC_MASK,
830 1,
831 1);
832
833 // Add event type icons to ImageList
834 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
835 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
836 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
837
838 // Assign ImageList to List View
839 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
840
841 // Now set up the listview with its columns.
842 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
843 lvc.cx = 90;
844 LoadStringW(hInstance,
845 IDS_COLUMNTYPE,
846 szTemp,
847 sizeof(szTemp) / sizeof(WCHAR));
848 lvc.pszText = szTemp;
849 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
850
851 lvc.cx = 70;
852 LoadStringW(hInstance,
853 IDS_COLUMNDATE,
854 szTemp,
855 sizeof(szTemp) / sizeof(WCHAR));
856 lvc.pszText = szTemp;
857 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
858
859 lvc.cx = 70;
860 LoadStringW(hInstance,
861 IDS_COLUMNTIME,
862 szTemp,
863 sizeof(szTemp) / sizeof(WCHAR));
864 lvc.pszText = szTemp;
865 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
866
867 lvc.cx = 150;
868 LoadStringW(hInstance,
869 IDS_COLUMNSOURCE,
870 szTemp,
871 sizeof(szTemp) / sizeof(WCHAR));
872 lvc.pszText = szTemp;
873 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
874
875 lvc.cx = 100;
876 LoadStringW(hInstance,
877 IDS_COLUMNCATEGORY,
878 szTemp,
879 sizeof(szTemp) / sizeof(WCHAR));
880 lvc.pszText = szTemp;
881 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
882
883 lvc.cx = 60;
884 LoadStringW(hInstance,
885 IDS_COLUMNEVENT,
886 szTemp,
887 sizeof(szTemp) / sizeof(WCHAR));
888 lvc.pszText = szTemp;
889 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
890
891 lvc.cx = 120;
892 LoadStringW(hInstance,
893 IDS_COLUMNUSER,
894 szTemp,
895 sizeof(szTemp) / sizeof(WCHAR));
896 lvc.pszText = szTemp;
897 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
898
899 lvc.cx = 100;
900 LoadStringW(hInstance,
901 IDS_COLUMNCOMPUTER,
902 szTemp,
903 sizeof(szTemp) / sizeof(WCHAR));
904 lvc.pszText = szTemp;
905 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
906
907 lvc.cx = 0;
908 LoadStringW(hInstance,
909 IDS_COLUMNEVENTDATA,
910 szTemp,
911 sizeof(szTemp) / sizeof(WCHAR));
912 lvc.pszText = szTemp;
913 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
914
915 ShowWindow(hwndMainWindow, nCmdShow);
916 UpdateWindow(hwndMainWindow);
917
918 QueryEventMessages(lpComputerName, // Use the local computer.
919 EVENT_SOURCE_APPLICATION); // The event log category
920
921 return TRUE;
922 }
923
924
925 //
926 // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
927 //
928 // PURPOSE: Processes messages for the main window.
929 //
930 // WM_COMMAND - process the application menu
931 // WM_PAINT - Paint the main window
932 // WM_DESTROY - post a quit message and return
933 //
934 //
935 LRESULT CALLBACK
936 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
937 {
938 RECT rect;
939 NMHDR *hdr;
940
941 switch (message)
942 {
943 case WM_CREATE:
944 CheckMenuRadioItem(GetMenu(hWnd),
945 ID_LOG_APPLICATION,
946 ID_LOG_SYSTEM,
947 ID_LOG_APPLICATION,
948 MF_BYCOMMAND);
949 break;
950
951 case WM_NOTIFY:
952 switch (((LPNMHDR)lParam)->code)
953 {
954 case NM_DBLCLK :
955 hdr = (NMHDR FAR*)lParam;
956 if (hdr->hwndFrom == hwndListView)
957 {
958 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
959
960 if (lpnmitem->iItem != -1)
961 {
962 DialogBox(hInst,
963 MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG),
964 hWnd,
965 EventDetails);
966 }
967 }
968 break;
969 }
970 break;
971
972 case WM_COMMAND:
973 // Parse the menu selections:
974 switch (LOWORD(wParam))
975 {
976 case ID_LOG_APPLICATION:
977 if (QueryEventMessages(lpComputerName, // Use the local computer.
978 EVENT_SOURCE_APPLICATION)) // The event log category
979 {
980 CheckMenuRadioItem(GetMenu(hWnd),
981 ID_LOG_APPLICATION,
982 ID_LOG_SYSTEM,
983 ID_LOG_APPLICATION,
984 MF_BYCOMMAND);
985 }
986 break;
987
988 case ID_LOG_SECURITY:
989 if (QueryEventMessages(lpComputerName, // Use the local computer.
990 EVENT_SOURCE_SECURITY)) // The event log category
991 {
992 CheckMenuRadioItem(GetMenu(hWnd),
993 ID_LOG_APPLICATION,
994 ID_LOG_SYSTEM,
995 ID_LOG_SECURITY,
996 MF_BYCOMMAND);
997 }
998 break;
999
1000 case ID_LOG_SYSTEM:
1001 if (QueryEventMessages(lpComputerName, // Use the local computer.
1002 EVENT_SOURCE_SYSTEM)) // The event log category
1003 {
1004 CheckMenuRadioItem(GetMenu(hWnd),
1005 ID_LOG_APPLICATION,
1006 ID_LOG_SYSTEM,
1007 ID_LOG_SYSTEM,
1008 MF_BYCOMMAND);
1009 }
1010 break;
1011
1012 case IDM_REFRESH:
1013 Refresh();
1014 break;
1015
1016 case IDM_ABOUT:
1017 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
1018 break;
1019
1020 case IDM_HELP:
1021 MessageBoxW(NULL,
1022 L"Help not implemented yet!",
1023 L"Event Log",
1024 MB_OK | MB_ICONINFORMATION);
1025 break;
1026
1027 case IDM_EXIT:
1028 DestroyWindow(hWnd);
1029 break;
1030
1031 default:
1032 return DefWindowProc(hWnd, message, wParam, lParam);
1033 }
1034 break;
1035
1036 case WM_SIZE:
1037 {
1038 // Gets the window rectangle
1039 GetClientRect(hWnd, &rect);
1040
1041 // Relocate the listview
1042 MoveWindow(hwndListView,
1043 0,
1044 0,
1045 rect.right,
1046 rect.bottom - 20,
1047 1);
1048
1049 // Resize the statusbar;
1050 SendMessage(hwndStatus, message, wParam, lParam);
1051 }
1052 break;
1053 case WM_DESTROY:
1054 FreeRecords();
1055 PostQuitMessage(0);
1056 break;
1057
1058 default:
1059 return DefWindowProc(hWnd, message, wParam, lParam);
1060 }
1061
1062 return 0;
1063 }
1064
1065
1066 // Message handler for about box.
1067 INT_PTR CALLBACK
1068 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1069 {
1070 UNREFERENCED_PARAMETER(lParam);
1071 switch (message)
1072 {
1073 case WM_INITDIALOG:
1074 {
1075 return (INT_PTR)TRUE;
1076 }
1077
1078 case WM_COMMAND:
1079 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1080 {
1081 EndDialog(hDlg, LOWORD(wParam));
1082 return (INT_PTR)TRUE;
1083 }
1084 break;
1085 }
1086
1087 return (INT_PTR)FALSE;
1088 }
1089
1090 VOID
1091 DisplayEvent(HWND hDlg)
1092 {
1093 WCHAR szEventType[MAX_PATH];
1094 WCHAR szTime[MAX_PATH];
1095 WCHAR szDate[MAX_PATH];
1096 WCHAR szUser[MAX_PATH];
1097 WCHAR szComputer[MAX_PATH];
1098 WCHAR szSource[MAX_PATH];
1099 WCHAR szCategory[MAX_PATH];
1100 WCHAR szEventID[MAX_PATH];
1101 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1102 WCHAR szEventData[MAX_PATH];
1103 BOOL bEventData = FALSE;
1104 LVITEMW li;
1105 EVENTLOGRECORD* pevlr;
1106 int iIndex;
1107
1108 // Get index of selected item
1109 iIndex = (int)SendMessage (hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1110
1111 li.mask = LVIF_PARAM;
1112 li.iItem = iIndex;
1113 li.iSubItem = 0;
1114
1115 (void)ListView_GetItem(hwndListView, &li);
1116
1117 pevlr = (EVENTLOGRECORD*)li.lParam;
1118
1119 if (iIndex != -1)
1120 {
1121 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType) * sizeof(WCHAR));
1122 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate) * sizeof(WCHAR));
1123 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime) * sizeof(WCHAR));
1124 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource) * sizeof(WCHAR));
1125 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory) * sizeof(WCHAR));
1126 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID) * sizeof(WCHAR));
1127 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser) * sizeof(WCHAR));
1128 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer) * sizeof(WCHAR));
1129
1130 bEventData = !(pevlr->DataLength == 0);
1131
1132 if (pevlr->DataLength > 0)
1133 {
1134 MultiByteToWideChar(CP_ACP,
1135 0,
1136 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1137 pevlr->DataLength,
1138 szEventData,
1139 MAX_PATH);
1140 }
1141
1142 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1143
1144 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1145 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1146
1147 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
1148 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
1149
1150 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
1151 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1152 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1153 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1154 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
1155 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1156 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1157 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, szEventData);
1158 }
1159 else
1160 {
1161 MessageBoxW(NULL,
1162 L"No Items in ListView",
1163 L"Error",
1164 MB_OK | MB_ICONINFORMATION);
1165 }
1166 }
1167
1168
1169 static
1170 INT_PTR CALLBACK
1171 StatusMessageWindowProc(IN HWND hwndDlg,
1172 IN UINT uMsg,
1173 IN WPARAM wParam,
1174 IN LPARAM lParam)
1175 {
1176 UNREFERENCED_PARAMETER(wParam);
1177
1178 switch (uMsg)
1179 {
1180 case WM_INITDIALOG:
1181 {
1182 return TRUE;
1183 }
1184 }
1185 return FALSE;
1186 }
1187
1188
1189 // Message handler for event details box.
1190 INT_PTR CALLBACK
1191 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1192 {
1193 UNREFERENCED_PARAMETER(lParam);
1194
1195 switch (message)
1196 {
1197 case WM_INITDIALOG:
1198 // Show event info on dialog box
1199 DisplayEvent(hDlg);
1200 return (INT_PTR)TRUE;
1201
1202 case WM_COMMAND:
1203 switch (LOWORD(wParam))
1204 {
1205 case IDOK:
1206 case IDCANCEL:
1207 EndDialog(hDlg, LOWORD(wParam));
1208 return (INT_PTR)TRUE;
1209
1210 case IDPREVIOUS:
1211 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1212
1213 // Show event info on dialog box
1214 DisplayEvent(hDlg);
1215 return (INT_PTR)TRUE;
1216
1217 case IDNEXT:
1218 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1219
1220 // Show event info on dialog box
1221 DisplayEvent(hDlg);
1222 return (INT_PTR)TRUE;
1223
1224 case IDC_BYTESRADIO:
1225 return (INT_PTR)TRUE;
1226
1227 case IDC_WORDRADIO:
1228 return (INT_PTR)TRUE;
1229
1230 case IDHELP:
1231 MessageBoxW(NULL,
1232 L"Help not implemented yet!",
1233 L"Event Log",
1234 MB_OK | MB_ICONINFORMATION);
1235 return (INT_PTR)TRUE;
1236
1237 default:
1238 break;
1239 }
1240 break;
1241 }
1242
1243 return (INT_PTR)FALSE;
1244 }