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