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