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