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