Sync with trunk r63935.
[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 <wingdi.h>
32 #include <winnls.h>
33 #include <winreg.h>
34 #include <commctrl.h>
35 #include <commdlg.h>
36
37 #include "resource.h"
38
39 #if _MSC_VER
40 #pragma warning(disable: 4996) /* 'strdup' was declared deprecated */
41 #define _CRT_SECURE_NO_DEPRECATE /* all deprecated unsafe string functions */
42 #endif
43
44 static const WCHAR szWindowClass[] = L"EVENTVWR"; /* the main window class name*/
45 static const WCHAR EVENTLOG_BASE_KEY[] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\";
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 WCHAR szSaveFilter[MAX_LOADSTRING]; /* Filter Mask for the save Dialog */
62 HWND hwndMainWindow; /* Main window */
63 HWND hwndListView; /* ListView control */
64 HWND hwndStatus; /* Status bar */
65 HMENU hMainMenu; /* The application's main menu */
66 WCHAR szStatusBarTemplate[MAX_LOADSTRING]; /* The status bar text */
67 PEVENTLOGRECORD *g_RecordPtrs = NULL;
68 DWORD g_TotalRecords = 0;
69 OPENFILENAMEW sfn;
70
71 LPWSTR lpSourceLogName = NULL;
72 LPWSTR lpComputerName = NULL;
73
74 DWORD dwNumLogs = 0;
75 WCHAR **LogNames;
76
77 /* Forward declarations of functions included in this code module: */
78 ATOM MyRegisterClass(HINSTANCE hInstance);
79 BOOL InitInstance(HINSTANCE, int);
80 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
81 INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
82 INT_PTR CALLBACK EventDetails(HWND, UINT, WPARAM, LPARAM);
83 static INT_PTR CALLBACK StatusMessageWindowProc (HWND, UINT, WPARAM, LPARAM);
84
85
86 int APIENTRY
87 wWinMain(HINSTANCE hInstance,
88 HINSTANCE hPrevInstance,
89 LPWSTR lpCmdLine,
90 int nCmdShow)
91 {
92 MSG msg;
93 HACCEL hAccelTable;
94 INITCOMMONCONTROLSEX iccx;
95
96 UNREFERENCED_PARAMETER(hPrevInstance);
97 UNREFERENCED_PARAMETER(lpCmdLine);
98
99 /* Whenever any of the common controls are used in your app,
100 * you must call InitCommonControlsEx() to register the classes
101 * for those controls. */
102 iccx.dwSize = sizeof(INITCOMMONCONTROLSEX);
103 iccx.dwICC = ICC_LISTVIEW_CLASSES;
104 InitCommonControlsEx(&iccx);
105
106 /* Initialize global strings */
107 LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
108 LoadStringW(hInstance, IDS_APP_TITLE_EX, szTitleTemplate, MAX_LOADSTRING);
109 LoadStringW(hInstance, IDS_STATUS_MSG, szStatusBarTemplate, MAX_LOADSTRING);
110 MyRegisterClass(hInstance);
111
112 /* Perform application initialization: */
113 if (!InitInstance(hInstance, nCmdShow))
114 {
115 return FALSE;
116 }
117
118 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EVENTVWR));
119
120 /* Main message loop: */
121 while (GetMessageW(&msg, NULL, 0, 0))
122 {
123 if (!TranslateAcceleratorW(msg.hwnd, hAccelTable, &msg))
124 {
125 TranslateMessage(&msg);
126 DispatchMessage(&msg);
127 }
128 }
129
130 return (int)msg.wParam;
131 }
132
133 static void FreeRecords(void)
134 {
135 DWORD iIndex;
136
137 if (!g_RecordPtrs)
138 return;
139
140 for (iIndex = 0; iIndex < g_TotalRecords; iIndex++)
141 HeapFree(GetProcessHeap(), 0, g_RecordPtrs[iIndex]);
142 HeapFree(GetProcessHeap(), 0, g_RecordPtrs);
143 g_RecordPtrs = NULL;
144 }
145
146 VOID
147 ShowLastWin32Error(VOID)
148 {
149 DWORD dwError;
150 LPWSTR lpMessageBuffer;
151
152 dwError = GetLastError();
153 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
154 NULL,
155 dwError,
156 0,
157 (LPWSTR)&lpMessageBuffer,
158 0,
159 NULL);
160
161 MessageBoxW(hwndMainWindow, lpMessageBuffer, szTitle, MB_OK | MB_ICONERROR);
162 LocalFree(lpMessageBuffer);
163 }
164
165 VOID
166 EventTimeToSystemTime(DWORD EventTime,
167 SYSTEMTIME *pSystemTime)
168 {
169 SYSTEMTIME st1970 = { 1970, 1, 0, 1, 0, 0, 0, 0 };
170 FILETIME ftLocal;
171 union
172 {
173 FILETIME ft;
174 ULONGLONG ll;
175 } u1970, uUCT;
176
177 uUCT.ft.dwHighDateTime = 0;
178 uUCT.ft.dwLowDateTime = EventTime;
179 SystemTimeToFileTime(&st1970, &u1970.ft);
180 uUCT.ll = uUCT.ll * 10000000 + u1970.ll;
181 FileTimeToLocalFileTime(&uUCT.ft, &ftLocal);
182 FileTimeToSystemTime(&ftLocal, pSystemTime);
183 }
184
185
186 void
187 TrimNulls(LPWSTR s)
188 {
189 WCHAR *c;
190
191 if (s != NULL)
192 {
193 c = s + wcslen(s) - 1;
194 while (c >= s && iswspace(*c))
195 --c;
196 *++c = L'\0';
197 }
198 }
199
200
201 BOOL
202 GetEventMessageFileDLL(IN LPCWSTR lpLogName,
203 IN LPCWSTR SourceName,
204 IN LPCWSTR EntryName,
205 OUT LPWSTR ExpandedName)
206 {
207 DWORD dwSize;
208 BYTE szModuleName[MAX_PATH];
209 WCHAR szKeyName[MAX_PATH];
210 HKEY hAppKey = NULL;
211 HKEY hSourceKey = NULL;
212 BOOL bReturn = FALSE;
213
214 wcscpy(szKeyName, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\");
215 wcscat(szKeyName, lpLogName);
216
217 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
218 szKeyName,
219 0,
220 KEY_READ,
221 &hAppKey) == ERROR_SUCCESS)
222 {
223 if (RegOpenKeyExW(hAppKey,
224 SourceName,
225 0,
226 KEY_READ,
227 &hSourceKey) == ERROR_SUCCESS)
228 {
229 dwSize = MAX_PATH;
230 if (RegQueryValueExW(hSourceKey,
231 EntryName,
232 NULL,
233 NULL,
234 (LPBYTE)szModuleName,
235 &dwSize) == ERROR_SUCCESS)
236 {
237 /* Returns a string containing the requested substituted environment variable. */
238 ExpandEnvironmentStringsW((LPCWSTR)szModuleName, ExpandedName, MAX_PATH);
239
240 /* Successful */
241 bReturn = TRUE;
242 }
243 }
244 }
245 else
246 {
247 ShowLastWin32Error();
248 }
249
250 if (hSourceKey != NULL)
251 RegCloseKey(hSourceKey);
252
253 if (hAppKey != NULL)
254 RegCloseKey(hAppKey);
255
256 return bReturn;
257 }
258
259
260 BOOL
261 GetEventCategory(IN LPCWSTR KeyName,
262 IN LPCWSTR SourceName,
263 IN EVENTLOGRECORD *pevlr,
264 OUT LPWSTR CategoryName)
265 {
266 HANDLE hLibrary = NULL;
267 WCHAR szMessageDLL[MAX_PATH];
268 LPVOID lpMsgBuf = NULL;
269
270 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_CATEGORY_MESSAGE_FILE , szMessageDLL))
271 {
272 hLibrary = LoadLibraryExW(szMessageDLL,
273 NULL,
274 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
275 if (hLibrary != NULL)
276 {
277 /* Retrieve the message string. */
278 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
279 hLibrary,
280 pevlr->EventCategory,
281 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
282 (LPWSTR)&lpMsgBuf,
283 EVENT_MESSAGE_FILE_BUFFER,
284 NULL) != 0)
285 {
286 /* Trim the string */
287 TrimNulls(lpMsgBuf);
288
289 /* Copy the category name */
290 wcscpy(CategoryName, lpMsgBuf);
291 }
292 else
293 {
294 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
295 }
296
297 if (hLibrary != NULL)
298 FreeLibrary(hLibrary);
299
300 /* Free the buffer allocated by FormatMessage */
301 if (lpMsgBuf)
302 LocalFree(lpMsgBuf);
303
304 return TRUE;
305 }
306 }
307
308 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
309
310 return FALSE;
311 }
312
313
314 BOOL
315 GetEventMessage(IN LPCWSTR KeyName,
316 IN LPCWSTR SourceName,
317 IN EVENTLOGRECORD *pevlr,
318 OUT LPWSTR EventText)
319 {
320 DWORD i;
321 HANDLE hLibrary = NULL;
322 WCHAR SourceModuleName[1000];
323 WCHAR ParameterModuleName[1000];
324 LPWSTR lpMsgBuf = NULL;
325 WCHAR szStringIDNotFound[MAX_LOADSTRING];
326 LPWSTR szDll;
327 LPWSTR szMessage;
328 LPWSTR *szArguments;
329 BOOL bDone = FALSE;
330
331 /* TODO : GetEventMessageFileDLL can return a comma separated list of DLLs */
332 if (GetEventMessageFileDLL (KeyName, SourceName, EVENT_MESSAGE_FILE, SourceModuleName))
333 {
334 /* Get the event message */
335 szMessage = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
336
337 /* Allocate space for parameters */
338 szArguments = malloc(sizeof(LPVOID) * pevlr->NumStrings);
339 if (!szArguments)
340 {
341 return FALSE;
342 }
343
344 for (i = 0; i < pevlr->NumStrings ; i++)
345 {
346 if (wcsstr(szMessage , L"%%"))
347 {
348 if (GetEventMessageFileDLL(KeyName, SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
349 {
350 /* Not yet support for reading messages from parameter message DLL */
351 }
352 }
353
354 szArguments[i] = szMessage;
355 szMessage += wcslen(szMessage) + 1;
356 }
357
358 szDll = wcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
359 while ((szDll != NULL) && (!bDone))
360 {
361 hLibrary = LoadLibraryExW(szDll,
362 NULL,
363 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
364 if (hLibrary == NULL)
365 {
366 /* The DLL could not be loaded try the next one (if any) */
367 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
368 }
369 else
370 {
371 /* Retrieve the message string. */
372 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
373 FORMAT_MESSAGE_ALLOCATE_BUFFER |
374 FORMAT_MESSAGE_FROM_HMODULE |
375 FORMAT_MESSAGE_ARGUMENT_ARRAY,
376 hLibrary,
377 pevlr->EventID,
378 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
379 (LPWSTR)&lpMsgBuf,
380 0,
381 (va_list*)szArguments) == 0)
382 {
383 /* We haven't found the string , get next DLL (if any) */
384 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
385 }
386 else
387 {
388 if (lpMsgBuf)
389 {
390 /* The ID was found and the message was formated */
391 bDone = TRUE;
392
393 /* Trim the string */
394 TrimNulls((LPWSTR)lpMsgBuf);
395
396 /* Copy the event text */
397 wcscpy(EventText ,lpMsgBuf);
398 }
399 }
400
401 FreeLibrary(hLibrary);
402 }
403 }
404
405 if (!bDone)
406 {
407 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
408 swprintf(EventText, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
409 }
410
411 free(szArguments);
412
413 /* No more dlls to try, return result */
414 return bDone;
415 }
416
417 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, MAX_LOADSTRING);
418 swprintf(EventText, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
419
420 return FALSE;
421 }
422
423
424 VOID
425 GetEventType(IN WORD dwEventType,
426 OUT LPWSTR eventTypeText)
427 {
428 switch (dwEventType)
429 {
430 case EVENTLOG_ERROR_TYPE:
431 LoadStringW(hInst, IDS_EVENTLOG_ERROR_TYPE, eventTypeText, MAX_LOADSTRING);
432 break;
433 case EVENTLOG_WARNING_TYPE:
434 LoadStringW(hInst, IDS_EVENTLOG_WARNING_TYPE, eventTypeText, MAX_LOADSTRING);
435 break;
436 case EVENTLOG_INFORMATION_TYPE:
437 LoadStringW(hInst, IDS_EVENTLOG_INFORMATION_TYPE, eventTypeText, MAX_LOADSTRING);
438 break;
439 case EVENTLOG_AUDIT_SUCCESS:
440 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_SUCCESS, eventTypeText, MAX_LOADSTRING);
441 break;
442 case EVENTLOG_AUDIT_FAILURE:
443 LoadStringW(hInst, IDS_EVENTLOG_AUDIT_FAILURE, eventTypeText, MAX_LOADSTRING);
444 break;
445 case EVENTLOG_SUCCESS:
446 LoadStringW(hInst, IDS_EVENTLOG_SUCCESS, eventTypeText, MAX_LOADSTRING);
447 break;
448 default:
449 LoadStringW(hInst, IDS_EVENTLOG_UNKNOWN_TYPE, eventTypeText, MAX_LOADSTRING);
450 break;
451 }
452 }
453
454 BOOL
455 GetEventUserName(EVENTLOGRECORD *pelr,
456 OUT LPWSTR pszUser)
457 {
458 PSID lpSid;
459 WCHAR szName[1024];
460 WCHAR szDomain[1024];
461 SID_NAME_USE peUse;
462 DWORD cbName = 1024;
463 DWORD cbDomain = 1024;
464
465 /* Point to the SID. */
466 lpSid = (PSID)((LPBYTE)pelr + pelr->UserSidOffset);
467
468 /* User SID */
469 if (pelr->UserSidLength > 0)
470 {
471 if (LookupAccountSidW(NULL,
472 lpSid,
473 szName,
474 &cbName,
475 szDomain,
476 &cbDomain,
477 &peUse))
478 {
479 wcscpy(pszUser, szName);
480 return TRUE;
481 }
482 }
483
484 return FALSE;
485 }
486
487
488 static DWORD WINAPI
489 ShowStatusMessageThread(IN LPVOID lpParameter)
490 {
491 HWND *phWnd = (HWND *)lpParameter;
492 HWND hWnd;
493 MSG Msg;
494
495 hWnd = CreateDialogParam(hInst,
496 MAKEINTRESOURCE(IDD_PROGRESSBOX),
497 GetDesktopWindow(),
498 StatusMessageWindowProc,
499 (LPARAM)NULL);
500 if (!hWnd)
501 return 0;
502
503 *phWnd = hWnd;
504
505 ShowWindow(hWnd, SW_SHOW);
506
507 /* Message loop for the Status window */
508 while (GetMessage(&Msg, NULL, 0, 0))
509 {
510 TranslateMessage(&Msg);
511 DispatchMessage(&Msg);
512 }
513
514 return 0;
515 }
516
517
518 BOOL
519 QueryEventMessages(LPWSTR lpMachineName,
520 LPWSTR lpLogName)
521 {
522 HWND hwndDlg;
523 HANDLE hEventLog;
524 EVENTLOGRECORD *pevlr;
525 DWORD dwRead, dwNeeded, dwThisRecord, dwTotalRecords = 0, dwCurrentRecord = 0, dwRecordsToRead = 0, dwFlags, dwMaxLength;
526 LPWSTR lpSourceName;
527 LPWSTR lpComputerName;
528 LPSTR lpData;
529 BOOL bResult = TRUE; /* Read succeeded. */
530 int i;
531
532 WCHAR szWindowTitle[MAX_PATH];
533 WCHAR szStatusText[MAX_PATH];
534 WCHAR szLocalDate[MAX_PATH];
535 WCHAR szLocalTime[MAX_PATH];
536 WCHAR szEventID[MAX_PATH];
537 WCHAR szEventTypeText[MAX_PATH];
538 WCHAR szCategoryID[MAX_PATH];
539 WCHAR szUsername[MAX_PATH];
540 WCHAR szEventText[EVENT_MESSAGE_FILE_BUFFER];
541 WCHAR szCategory[MAX_PATH];
542 WCHAR szData[MAX_PATH];
543
544 SYSTEMTIME time;
545 LVITEMW lviEventItem;
546
547 dwFlags = EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ;
548
549 /* Open the event log. */
550 hEventLog = OpenEventLogW(lpMachineName,
551 lpLogName);
552 if (hEventLog == NULL)
553 {
554 ShowLastWin32Error();
555 return FALSE;
556 }
557
558 lpSourceLogName = lpLogName;
559 lpComputerName = lpMachineName;
560
561 /* Disable listview redraw */
562 SendMessage(hwndListView, WM_SETREDRAW, FALSE, 0);
563
564 /* Clear the list view */
565 (void)ListView_DeleteAllItems (hwndListView);
566 FreeRecords();
567
568 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
569
570 /* Get the total number of event log records. */
571 GetNumberOfEventLogRecords (hEventLog , &dwTotalRecords);
572 g_TotalRecords = dwTotalRecords;
573
574 if (dwTotalRecords > 0)
575 {
576 EnableMenuItem(hMainMenu, ID_CLEAR_EVENTS, MF_BYCOMMAND | MF_ENABLED);
577 EnableMenuItem(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_ENABLED);
578 }
579 else
580 {
581 EnableMenuItem(hMainMenu, ID_CLEAR_EVENTS, MF_BYCOMMAND | MF_GRAYED);
582 EnableMenuItem(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_GRAYED);
583 }
584
585 g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(PVOID));
586
587 /* If we have at least 1000 records show the waiting dialog */
588 if (dwTotalRecords > 1000)
589 {
590 CloseHandle(CreateThread(NULL,
591 0,
592 ShowStatusMessageThread,
593 (LPVOID)&hwndDlg,
594 0,
595 NULL));
596 }
597
598 while (dwCurrentRecord < dwTotalRecords)
599 {
600 pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD) * dwTotalRecords);
601 g_RecordPtrs[dwCurrentRecord] = pevlr;
602
603 bResult = ReadEventLog(hEventLog, // Event log handle
604 dwFlags, // Sequential read
605 0, // Ignored for sequential read
606 pevlr, // Pointer to buffer
607 sizeof(EVENTLOGRECORD), // Size of buffer
608 &dwRead, // Number of bytes read
609 &dwNeeded); // Bytes in the next record
610 if((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
611 {
612 HeapFree(GetProcessHeap(), 0, pevlr);
613 pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded);
614 g_RecordPtrs[dwCurrentRecord] = pevlr;
615
616 ReadEventLogW(hEventLog, // event log handle
617 dwFlags, // read flags
618 0, // offset; default is 0
619 pevlr, // pointer to buffer
620 dwNeeded, // size of buffer
621 &dwRead, // number of bytes read
622 &dwNeeded); // bytes in next record
623 }
624
625 while (dwRead > 0)
626 {
627 LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, MAX_PATH);
628 LoadStringW(hInst, IDS_NOT_AVAILABLE, szEventText, MAX_PATH);
629 LoadStringW(hInst, IDS_NONE, szCategory, MAX_PATH);
630
631 // Get the event source name.
632 lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
633
634 // Get the computer name
635 lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR));
636
637 // This ist the data section of the current event
638 lpData = (LPSTR)((LPBYTE)pevlr + pevlr->DataOffset);
639
640 // Compute the event type
641 EventTimeToSystemTime(pevlr->TimeWritten, &time);
642
643 // Get the username that generated the event
644 GetEventUserName(pevlr, szUsername);
645
646 GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, szLocalDate, MAX_PATH);
647 GetTimeFormatW(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &time, NULL, szLocalTime, MAX_PATH);
648
649 GetEventType(pevlr->EventType, szEventTypeText);
650 GetEventCategory(lpLogName, lpSourceName, pevlr, szCategory);
651
652 swprintf(szEventID, L"%u", (pevlr->EventID & 0xFFFF));
653 swprintf(szCategoryID, L"%u", pevlr->EventCategory);
654
655 lviEventItem.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
656 lviEventItem.iItem = 0;
657 lviEventItem.iSubItem = 0;
658 lviEventItem.lParam = (LPARAM)pevlr;
659 lviEventItem.pszText = szEventTypeText;
660
661 switch (pevlr->EventType)
662 {
663 case EVENTLOG_ERROR_TYPE:
664 lviEventItem.iImage = 2;
665 break;
666
667 case EVENTLOG_AUDIT_FAILURE:
668 lviEventItem.iImage = 2;
669 break;
670
671 case EVENTLOG_WARNING_TYPE:
672 lviEventItem.iImage = 1;
673 break;
674
675 case EVENTLOG_INFORMATION_TYPE:
676 lviEventItem.iImage = 0;
677 break;
678
679 case EVENTLOG_AUDIT_SUCCESS:
680 lviEventItem.iImage = 0;
681 break;
682
683 case EVENTLOG_SUCCESS:
684 lviEventItem.iImage = 0;
685 break;
686 }
687
688 lviEventItem.iItem = ListView_InsertItem(hwndListView, &lviEventItem);
689
690 ListView_SetItemText(hwndListView, lviEventItem.iItem, 1, szLocalDate);
691 ListView_SetItemText(hwndListView, lviEventItem.iItem, 2, szLocalTime);
692 ListView_SetItemText(hwndListView, lviEventItem.iItem, 3, lpSourceName);
693 ListView_SetItemText(hwndListView, lviEventItem.iItem, 4, szCategory);
694 ListView_SetItemText(hwndListView, lviEventItem.iItem, 5, szEventID);
695 ListView_SetItemText(hwndListView, lviEventItem.iItem, 6, szUsername); //User
696 ListView_SetItemText(hwndListView, lviEventItem.iItem, 7, lpComputerName); //Computer
697 MultiByteToWideChar(CP_ACP,
698 0,
699 lpData,
700 pevlr->DataLength,
701 szData,
702 MAX_PATH);
703 ListView_SetItemText(hwndListView, lviEventItem.iItem, 8, szData); //Event Text
704
705 dwRead -= pevlr->Length;
706 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
707 }
708
709 dwRecordsToRead--;
710 dwCurrentRecord++;
711 }
712
713 // All events loaded
714 EndDialog(hwndDlg, 0);
715
716
717 i = swprintf(szWindowTitle, szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */
718 /* lpComputerName can be NULL here if no records was read */
719 dwMaxLength = sizeof(szWindowTitle) / sizeof(WCHAR) - i;
720 if(!lpComputerName)
721 GetComputerNameW(szWindowTitle+i, &dwMaxLength);
722 else
723 _snwprintf(szWindowTitle+i, dwMaxLength, L"%s", lpComputerName);
724
725 swprintf(szStatusText, szStatusBarTemplate, lpLogName, dwTotalRecords);
726
727 // Update the status bar
728 SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
729
730 // Set the window title
731 SetWindowTextW(hwndMainWindow, szWindowTitle);
732
733 // Resume list view redraw
734 SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
735
736 // Close the event log.
737 CloseEventLog(hEventLog);
738
739 return TRUE;
740 }
741
742
743 VOID
744 SaveProtocol(VOID)
745 {
746 HANDLE hEventLog;
747 WCHAR szFileName[MAX_PATH];
748
749 ZeroMemory(szFileName, sizeof(szFileName));
750
751 sfn.lpstrFile = szFileName;
752 sfn.nMaxFile = MAX_PATH;
753
754 if (!GetSaveFileNameW(&sfn))
755 {
756 return;
757 }
758
759 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
760 if (!hEventLog)
761 {
762 ShowLastWin32Error();
763 return;
764 }
765
766 if (!BackupEventLogW(hEventLog, szFileName))
767 {
768 ShowLastWin32Error();
769 }
770
771 CloseEventLog(hEventLog);
772 }
773
774
775 BOOL
776 ClearEvents(VOID)
777 {
778 HANDLE hEventLog;
779 WCHAR szFileName[MAX_PATH];
780 WCHAR szMessage[MAX_LOADSTRING];
781
782 ZeroMemory(szFileName, sizeof(szFileName));
783 ZeroMemory(szMessage, sizeof(szMessage));
784
785 LoadStringW(hInst, IDS_CLEAREVENTS_MSG, szMessage, MAX_LOADSTRING);
786
787 sfn.lpstrFile = szFileName;
788 sfn.nMaxFile = MAX_PATH;
789
790 switch (MessageBoxW(hwndMainWindow, szMessage, szTitle, MB_YESNOCANCEL | MB_ICONINFORMATION))
791 {
792 case IDCANCEL:
793 {
794 return FALSE;
795 break;
796 }
797
798 case IDNO:
799 {
800 sfn.lpstrFile = NULL;
801 break;
802 }
803
804 case IDYES:
805 {
806 if (!GetSaveFileNameW(&sfn))
807 {
808 return FALSE;
809 }
810 break;
811 }
812 }
813
814 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
815 if (!hEventLog)
816 {
817 ShowLastWin32Error();
818 return FALSE;
819 }
820
821 if (!ClearEventLogW(hEventLog, sfn.lpstrFile))
822 {
823 ShowLastWin32Error();
824 CloseEventLog(hEventLog);
825 return FALSE;
826 }
827
828 CloseEventLog(hEventLog);
829
830 return TRUE;
831 }
832
833
834 VOID
835 Refresh(VOID)
836 {
837 QueryEventMessages(lpComputerName,
838 lpSourceLogName);
839 }
840
841
842 ATOM
843 MyRegisterClass(HINSTANCE hInstance)
844 {
845 WNDCLASSEXW wcex;
846
847 wcex.cbSize = sizeof(WNDCLASSEX);
848
849 wcex.style = 0;
850 wcex.lpfnWndProc = WndProc;
851 wcex.cbClsExtra = 0;
852 wcex.cbWndExtra = 0;
853 wcex.hInstance = hInstance;
854 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EVENTVWR));
855 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
856 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
857 wcex.lpszMenuName = MAKEINTRESOURCE(IDC_EVENTVWR);
858 wcex.lpszClassName = szWindowClass;
859 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
860
861 return RegisterClassExW(&wcex);
862 }
863
864
865 VOID
866 GetDisplayNameFile(LPCWSTR lpLogName, LPWSTR lpModuleName)
867 {
868 HKEY hKey;
869 WCHAR *KeyPath;
870 WCHAR szModuleName[MAX_PATH];
871 DWORD dwData;
872
873
874 KeyPath = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR));
875 if (!KeyPath)
876 {
877 return;
878 }
879
880 wcscpy(KeyPath, EVENTLOG_BASE_KEY);
881 wcscat(KeyPath, lpLogName);
882
883 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
884 {
885 HeapFree(GetProcessHeap(), 0, KeyPath);
886 return;
887 }
888
889 dwData = MAX_PATH;
890
891 if (RegQueryValueExW(hKey, L"DisplayNameFile", NULL, NULL, (LPBYTE)szModuleName, &dwData) == ERROR_SUCCESS)
892 {
893 ExpandEnvironmentStringsW(szModuleName, lpModuleName, MAX_PATH);
894 }
895
896 RegCloseKey(hKey);
897 HeapFree(GetProcessHeap(), 0, KeyPath);
898 }
899
900
901 DWORD
902 GetDisplayNameID(LPCWSTR lpLogName)
903 {
904 HKEY hKey;
905 WCHAR *KeyPath;
906 DWORD dwMessageID = 0;
907 DWORD dwData;
908
909 KeyPath = (WCHAR*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR));
910 if (!KeyPath)
911 {
912 return 0;
913 }
914
915 wcscpy(KeyPath, EVENTLOG_BASE_KEY);
916 wcscat(KeyPath, lpLogName);
917
918 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
919 {
920 HeapFree(GetProcessHeap(), 0, KeyPath);
921 return 0;
922 }
923
924 dwData = sizeof(dwMessageID);
925
926 RegQueryValueExW(hKey, L"DisplayNameID", NULL, NULL, (LPBYTE)&dwMessageID, &dwData);
927
928 RegCloseKey(hKey);
929 HeapFree(GetProcessHeap(), 0, KeyPath);
930
931 return dwMessageID;
932 }
933
934
935 VOID
936 BuildLogList(void)
937 {
938 HKEY hKey;
939 DWORD lpcName;
940 DWORD dwIndex;
941 DWORD dwMessageID;
942 DWORD dwMaxKeyLength;
943 WCHAR szModuleName[MAX_PATH];
944 LPWSTR lpDisplayName;
945 HANDLE hLibrary = NULL;
946
947 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, EVENTLOG_BASE_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
948 {
949 return;
950 }
951
952 if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumLogs, &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
953 {
954 RegCloseKey(hKey);
955 return;
956 }
957
958 if (!dwNumLogs)
959 {
960 RegCloseKey(hKey);
961 return;
962 }
963
964 LogNames = (WCHAR**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dwNumLogs + 1) * sizeof(WCHAR*));
965
966 if (!LogNames)
967 {
968 RegCloseKey(hKey);
969 return;
970 }
971
972 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
973 {
974 LogNames[dwIndex] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((dwMaxKeyLength + 1) * sizeof(WCHAR)));
975
976 if (LogNames[dwIndex] != NULL)
977 {
978 lpcName = dwMaxKeyLength + 1;
979
980 if (RegEnumKeyExW(hKey, dwIndex, LogNames[dwIndex], &lpcName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
981 {
982 lpDisplayName = NULL;
983
984 ZeroMemory(szModuleName, sizeof(szModuleName));
985 GetDisplayNameFile(LogNames[dwIndex], szModuleName);
986 dwMessageID = GetDisplayNameID(LogNames[dwIndex]);
987
988 hLibrary = LoadLibraryExW(szModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
989 if (hLibrary != NULL)
990 {
991 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE, hLibrary, dwMessageID, 0, (LPWSTR)&lpDisplayName, 0, NULL);
992 FreeLibrary(hLibrary);
993 }
994
995 if (lpDisplayName)
996 {
997 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, lpDisplayName);
998 }
999 else
1000 {
1001 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, LogNames[dwIndex]);
1002 }
1003
1004 LocalFree(lpDisplayName);
1005 }
1006 }
1007 }
1008
1009 InsertMenuW(hMainMenu, ID_SAVE_PROTOCOL, MF_BYCOMMAND | MF_SEPARATOR, ID_FIRST_LOG + dwIndex + 1, NULL);
1010
1011 RegCloseKey(hKey);
1012
1013 return;
1014 }
1015
1016
1017 VOID
1018 FreeLogList(void)
1019 {
1020 DWORD dwIndex;
1021
1022 if (!LogNames)
1023 {
1024 return;
1025 }
1026
1027 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
1028 {
1029 if (LogNames[dwIndex])
1030 {
1031 HeapFree(GetProcessHeap(), 0, LogNames[dwIndex]);
1032 }
1033
1034 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex, MF_BYCOMMAND);
1035 }
1036
1037 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex + 1, MF_BYCOMMAND);
1038
1039 HeapFree(GetProcessHeap(), 0, LogNames);
1040
1041 dwNumLogs = 0;
1042
1043 return;
1044 }
1045
1046
1047 BOOL
1048 InitInstance(HINSTANCE hInstance,
1049 int nCmdShow)
1050 {
1051 HIMAGELIST hSmall;
1052 LVCOLUMNW lvc = {0};
1053 WCHAR szTemp[256];
1054
1055 hInst = hInstance; // Store instance handle in our global variable
1056
1057 hwndMainWindow = CreateWindowW(szWindowClass,
1058 szTitle,
1059 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
1060 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
1061 NULL,
1062 NULL,
1063 hInstance,
1064 NULL);
1065 if (!hwndMainWindow)
1066 {
1067 return FALSE;
1068 }
1069
1070 hwndStatus = CreateWindowExW(0, // no extended styles
1071 STATUSCLASSNAMEW, // status bar
1072 L"Done.", // no text
1073 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
1074 0, 0, 0, 0, // x, y, cx, cy
1075 hwndMainWindow, // parent window
1076 (HMENU)100, // window ID
1077 hInstance, // instance
1078 NULL); // window data
1079
1080 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
1081 // and WS_BORDER to create the normal "sunken" look. Also note that
1082 // LVS_EX_ styles cannot be set in CreateWindowEx().
1083 hwndListView = CreateWindowExW(WS_EX_CLIENTEDGE,
1084 WC_LISTVIEWW,
1085 L"",
1086 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
1087 0,
1088 0,
1089 243,
1090 200,
1091 hwndMainWindow,
1092 NULL,
1093 hInstance,
1094 NULL);
1095
1096 // After the ListView is created, we can add extended list view styles.
1097 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
1098
1099 // Create the ImageList
1100 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1101 GetSystemMetrics(SM_CYSMICON),
1102 ILC_MASK,
1103 1,
1104 1);
1105
1106 // Add event type icons to ImageList
1107 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_INFORMATIONICON)));
1108 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WARNINGICON)));
1109 ImageList_AddIcon (hSmall, LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ERRORICON)));
1110
1111 // Assign ImageList to List View
1112 (void)ListView_SetImageList (hwndListView, hSmall, LVSIL_SMALL);
1113
1114 // Now set up the listview with its columns.
1115 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
1116 lvc.cx = 90;
1117 LoadStringW(hInstance,
1118 IDS_COLUMNTYPE,
1119 szTemp,
1120 sizeof(szTemp) / sizeof(WCHAR));
1121 lvc.pszText = szTemp;
1122 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
1123
1124 lvc.cx = 70;
1125 LoadStringW(hInstance,
1126 IDS_COLUMNDATE,
1127 szTemp,
1128 sizeof(szTemp) / sizeof(WCHAR));
1129 lvc.pszText = szTemp;
1130 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
1131
1132 lvc.cx = 70;
1133 LoadStringW(hInstance,
1134 IDS_COLUMNTIME,
1135 szTemp,
1136 sizeof(szTemp) / sizeof(WCHAR));
1137 lvc.pszText = szTemp;
1138 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
1139
1140 lvc.cx = 150;
1141 LoadStringW(hInstance,
1142 IDS_COLUMNSOURCE,
1143 szTemp,
1144 sizeof(szTemp) / sizeof(WCHAR));
1145 lvc.pszText = szTemp;
1146 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
1147
1148 lvc.cx = 100;
1149 LoadStringW(hInstance,
1150 IDS_COLUMNCATEGORY,
1151 szTemp,
1152 sizeof(szTemp) / sizeof(WCHAR));
1153 lvc.pszText = szTemp;
1154 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
1155
1156 lvc.cx = 60;
1157 LoadStringW(hInstance,
1158 IDS_COLUMNEVENT,
1159 szTemp,
1160 sizeof(szTemp) / sizeof(WCHAR));
1161 lvc.pszText = szTemp;
1162 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
1163
1164 lvc.cx = 120;
1165 LoadStringW(hInstance,
1166 IDS_COLUMNUSER,
1167 szTemp,
1168 sizeof(szTemp) / sizeof(WCHAR));
1169 lvc.pszText = szTemp;
1170 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
1171
1172 lvc.cx = 100;
1173 LoadStringW(hInstance,
1174 IDS_COLUMNCOMPUTER,
1175 szTemp,
1176 sizeof(szTemp) / sizeof(WCHAR));
1177 lvc.pszText = szTemp;
1178 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
1179
1180 lvc.cx = 0;
1181 LoadStringW(hInstance,
1182 IDS_COLUMNEVENTDATA,
1183 szTemp,
1184 sizeof(szTemp) / sizeof(WCHAR));
1185 lvc.pszText = szTemp;
1186 (void)ListView_InsertColumn(hwndListView, 8, &lvc);
1187
1188 // Initialize the save Dialog
1189 ZeroMemory(&sfn, sizeof(sfn));
1190 ZeroMemory(szSaveFilter, sizeof(szSaveFilter));
1191
1192 LoadStringW(hInst, IDS_SAVE_FILTER, szSaveFilter, MAX_LOADSTRING);
1193
1194 sfn.lStructSize = sizeof(sfn);
1195 sfn.hwndOwner = hwndMainWindow;
1196 sfn.hInstance = hInstance;
1197 sfn.lpstrFilter = szSaveFilter;
1198 sfn.lpstrInitialDir = NULL;
1199 sfn.Flags = OFN_HIDEREADONLY | OFN_SHAREAWARE;
1200 sfn.lpstrDefExt = NULL;
1201
1202 ShowWindow(hwndMainWindow, nCmdShow);
1203 UpdateWindow(hwndMainWindow);
1204
1205 BuildLogList();
1206
1207 QueryEventMessages(lpComputerName, LogNames[0]);
1208
1209 CheckMenuRadioItem(GetMenu(hwndMainWindow), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, ID_FIRST_LOG, MF_BYCOMMAND);
1210
1211 return TRUE;
1212 }
1213
1214
1215 LRESULT CALLBACK
1216 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1217 {
1218 RECT rect;
1219 NMHDR *hdr;
1220
1221 switch (message)
1222 {
1223 case WM_CREATE:
1224 hMainMenu = GetMenu(hWnd);
1225 break;
1226
1227 case WM_NOTIFY:
1228 switch (((LPNMHDR)lParam)->code)
1229 {
1230 case NM_DBLCLK :
1231 hdr = (NMHDR FAR*)lParam;
1232 if (hdr->hwndFrom == hwndListView)
1233 {
1234 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
1235
1236 if (lpnmitem->iItem != -1)
1237 {
1238 DialogBox(hInst,
1239 MAKEINTRESOURCE(IDD_EVENTDETAILDIALOG),
1240 hWnd,
1241 EventDetails);
1242 }
1243 }
1244 break;
1245 }
1246 break;
1247
1248 case WM_COMMAND:
1249 // Parse the menu selections:
1250
1251 if ((LOWORD(wParam) >= ID_FIRST_LOG) && (LOWORD(wParam) <= ID_FIRST_LOG + dwNumLogs))
1252 {
1253 if (LogNames[LOWORD(wParam) - ID_FIRST_LOG])
1254 {
1255 if (QueryEventMessages(lpComputerName, LogNames[LOWORD(wParam) - ID_FIRST_LOG]))
1256 {
1257 CheckMenuRadioItem(GetMenu(hWnd), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, LOWORD(wParam), MF_BYCOMMAND);
1258 }
1259 }
1260 }
1261 else
1262
1263 switch (LOWORD(wParam))
1264 {
1265 case ID_SAVE_PROTOCOL:
1266 SaveProtocol();
1267 break;
1268
1269 case ID_CLEAR_EVENTS:
1270 if (ClearEvents())
1271 {
1272 Refresh();
1273 }
1274 break;
1275
1276 case IDM_REFRESH:
1277 Refresh();
1278 break;
1279
1280 case IDM_ABOUT:
1281 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
1282 break;
1283
1284 case IDM_HELP:
1285 MessageBoxW(hwndMainWindow,
1286 L"Help not implemented yet!",
1287 L"Event Log",
1288 MB_OK | MB_ICONINFORMATION);
1289 break;
1290
1291 case IDM_EXIT:
1292 DestroyWindow(hWnd);
1293 break;
1294
1295 default:
1296 return DefWindowProc(hWnd, message, wParam, lParam);
1297 }
1298 break;
1299
1300 case WM_SIZE:
1301 {
1302 // Gets the window rectangle
1303 GetClientRect(hWnd, &rect);
1304
1305 // Relocate the listview
1306 MoveWindow(hwndListView,
1307 0,
1308 0,
1309 rect.right,
1310 rect.bottom - 20,
1311 1);
1312
1313 // Resize the statusbar;
1314 SendMessage(hwndStatus, message, wParam, lParam);
1315 }
1316 break;
1317 case WM_DESTROY:
1318 FreeRecords();
1319 FreeLogList();
1320 PostQuitMessage(0);
1321 break;
1322
1323 default:
1324 return DefWindowProc(hWnd, message, wParam, lParam);
1325 }
1326
1327 return 0;
1328 }
1329
1330
1331 // Message handler for about box.
1332 INT_PTR CALLBACK
1333 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1334 {
1335 UNREFERENCED_PARAMETER(lParam);
1336 switch (message)
1337 {
1338 case WM_INITDIALOG:
1339 {
1340 return (INT_PTR)TRUE;
1341 }
1342
1343 case WM_COMMAND:
1344 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1345 {
1346 EndDialog(hDlg, LOWORD(wParam));
1347 return (INT_PTR)TRUE;
1348 }
1349 break;
1350 }
1351
1352 return (INT_PTR)FALSE;
1353 }
1354
1355 VOID
1356 DisplayEvent(HWND hDlg)
1357 {
1358 WCHAR szEventType[MAX_PATH];
1359 WCHAR szTime[MAX_PATH];
1360 WCHAR szDate[MAX_PATH];
1361 WCHAR szUser[MAX_PATH];
1362 WCHAR szComputer[MAX_PATH];
1363 WCHAR szSource[MAX_PATH];
1364 WCHAR szCategory[MAX_PATH];
1365 WCHAR szEventID[MAX_PATH];
1366 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1367 WCHAR szEventData[MAX_PATH];
1368 BOOL bEventData = FALSE;
1369 LVITEMW li;
1370 EVENTLOGRECORD* pevlr;
1371 int iIndex;
1372
1373 // Get index of selected item
1374 iIndex = (int)SendMessage (hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1375
1376 li.mask = LVIF_PARAM;
1377 li.iItem = iIndex;
1378 li.iSubItem = 0;
1379
1380 (void)ListView_GetItem(hwndListView, &li);
1381
1382 pevlr = (EVENTLOGRECORD*)li.lParam;
1383
1384 if (iIndex != -1)
1385 {
1386 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, sizeof(szEventType) / sizeof(WCHAR));
1387 ListView_GetItemText(hwndListView, iIndex, 1, szDate, sizeof(szDate) / sizeof(WCHAR));
1388 ListView_GetItemText(hwndListView, iIndex, 2, szTime, sizeof(szTime) / sizeof(WCHAR));
1389 ListView_GetItemText(hwndListView, iIndex, 3, szSource, sizeof(szSource) / sizeof(WCHAR));
1390 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, sizeof(szCategory) / sizeof(WCHAR));
1391 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, sizeof(szEventID) / sizeof(WCHAR));
1392 ListView_GetItemText(hwndListView, iIndex, 6, szUser, sizeof(szUser) / sizeof(WCHAR));
1393 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, sizeof(szComputer) / sizeof(WCHAR));
1394
1395 bEventData = !(pevlr->DataLength == 0);
1396
1397 if (pevlr->DataLength > 0)
1398 {
1399 MultiByteToWideChar(CP_ACP,
1400 0,
1401 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1402 pevlr->DataLength,
1403 szEventData,
1404 MAX_PATH);
1405 }
1406
1407 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1408
1409 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1410 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1411
1412 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
1413 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
1414
1415 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
1416 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1417 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1418 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1419 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
1420 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1421 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1422 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, szEventData);
1423 }
1424 else
1425 {
1426 MessageBoxW(NULL,
1427 L"No Items in ListView",
1428 L"Error",
1429 MB_OK | MB_ICONINFORMATION);
1430 }
1431 }
1432
1433
1434 static
1435 INT_PTR CALLBACK
1436 StatusMessageWindowProc(IN HWND hwndDlg,
1437 IN UINT uMsg,
1438 IN WPARAM wParam,
1439 IN LPARAM lParam)
1440 {
1441 UNREFERENCED_PARAMETER(wParam);
1442
1443 switch (uMsg)
1444 {
1445 case WM_INITDIALOG:
1446 {
1447 return TRUE;
1448 }
1449 }
1450 return FALSE;
1451 }
1452
1453
1454 // Message handler for event details box.
1455 INT_PTR CALLBACK
1456 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1457 {
1458 UNREFERENCED_PARAMETER(lParam);
1459
1460 switch (message)
1461 {
1462 case WM_INITDIALOG:
1463 // Show event info on dialog box
1464 DisplayEvent(hDlg);
1465 return (INT_PTR)TRUE;
1466
1467 case WM_COMMAND:
1468 switch (LOWORD(wParam))
1469 {
1470 case IDOK:
1471 case IDCANCEL:
1472 EndDialog(hDlg, LOWORD(wParam));
1473 return (INT_PTR)TRUE;
1474
1475 case IDPREVIOUS:
1476 SendMessage(hwndListView, WM_KEYDOWN, VK_UP, 0);
1477
1478 // Show event info on dialog box
1479 DisplayEvent(hDlg);
1480 return (INT_PTR)TRUE;
1481
1482 case IDNEXT:
1483 SendMessage(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1484
1485 // Show event info on dialog box
1486 DisplayEvent(hDlg);
1487 return (INT_PTR)TRUE;
1488
1489 case IDC_BYTESRADIO:
1490 return (INT_PTR)TRUE;
1491
1492 case IDC_WORDRADIO:
1493 return (INT_PTR)TRUE;
1494
1495 case IDHELP:
1496 MessageBoxW(hDlg,
1497 L"Help not implemented yet!",
1498 L"Event Log",
1499 MB_OK | MB_ICONINFORMATION);
1500 return (INT_PTR)TRUE;
1501
1502 default:
1503 break;
1504 }
1505 break;
1506 }
1507
1508 return (INT_PTR)FALSE;
1509 }