[SCHANNEL]
[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_CATEGORY_MESSAGE_FILE L"CategoryMessageFile"
48 #define EVENT_MESSAGE_FILE L"EventMessageFile"
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 BOOL Success = FALSE;
264 HMODULE hLibrary = NULL;
265 WCHAR szMessageDLL[MAX_PATH];
266 LPWSTR lpMsgBuf = NULL;
267
268 if (!GetEventMessageFileDLL(KeyName, SourceName, EVENT_CATEGORY_MESSAGE_FILE, szMessageDLL))
269 goto Quit;
270
271 hLibrary = LoadLibraryExW(szMessageDLL, NULL,
272 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
273 if (hLibrary == NULL)
274 goto Quit;
275
276 /* Retrieve the message string. */
277 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
278 FORMAT_MESSAGE_ALLOCATE_BUFFER | 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 StringCchCopyW(CategoryName, MAX_PATH, lpMsgBuf);
291 }
292 else
293 {
294 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
295 }
296
297 /* Free the buffer allocated by FormatMessage */
298 if (lpMsgBuf)
299 LocalFree(lpMsgBuf);
300
301 if (hLibrary != NULL)
302 FreeLibrary(hLibrary);
303
304 Success = TRUE;
305
306 Quit:
307 if (!Success)
308 LoadStringW(hInst, IDS_NONE, CategoryName, MAX_PATH);
309
310 return Success;
311 }
312
313
314 BOOL
315 GetEventMessage(IN LPCWSTR KeyName,
316 IN LPCWSTR SourceName,
317 IN EVENTLOGRECORD *pevlr,
318 OUT PWCHAR EventText)
319 {
320 BOOL Success = FALSE;
321 DWORD i;
322 HMODULE hLibrary = NULL;
323 WCHAR SourceModuleName[1000];
324 WCHAR ParameterModuleName[1000];
325 BOOL IsParamModNameCached = FALSE;
326 LPWSTR lpMsgBuf = NULL;
327 WCHAR szStringIDNotFound[MAX_LOADSTRING];
328 LPWSTR szDll;
329 LPWSTR szMessage;
330 LPWSTR *szArguments;
331
332 /* NOTE: GetEventMessageFileDLL can return a comma-separated list of DLLs */
333
334 if (!GetEventMessageFileDLL(KeyName, SourceName, EVENT_MESSAGE_FILE, SourceModuleName))
335 {
336 // goto Quit;
337 return FALSE;
338 }
339
340 /* Get the event message */
341 szMessage = (LPWSTR)((LPBYTE)pevlr + pevlr->StringOffset);
342
343 /* Allocate space for parameters */
344 szArguments = HeapAlloc(GetProcessHeap(), 0, pevlr->NumStrings * sizeof(LPVOID));
345 if (!szArguments)
346 {
347 // goto Quit;
348 return FALSE;
349 }
350
351 for (i = 0; i < pevlr->NumStrings; i++)
352 {
353 if (wcsstr(szMessage, L"%%"))
354 {
355 if (!IsParamModNameCached && GetEventMessageFileDLL(KeyName, SourceName, EVENT_PARAMETER_MESSAGE_FILE, ParameterModuleName))
356 {
357 /* Now that the parameter file list is loaded, no need to reload it at the next run! */
358 IsParamModNameCached = TRUE;
359
360 /* Not yet support for reading messages from parameter message DLL */
361 }
362 }
363
364 szArguments[i] = szMessage;
365 szMessage += wcslen(szMessage) + 1;
366 }
367
368 /* Loop through the list of event message DLLs */
369 szDll = wcstok(SourceModuleName, EVENT_DLL_SEPARATOR);
370 while ((szDll != NULL) && (!Success))
371 {
372 hLibrary = LoadLibraryExW(szDll, NULL,
373 DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
374 if (hLibrary == NULL)
375 {
376 /* The DLL could not be loaded try the next one (if any) */
377 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
378 continue;
379 }
380
381 /* Retrieve the message string. */
382 if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE |
383 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY,
384 hLibrary,
385 pevlr->EventID,
386 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
387 (LPWSTR)&lpMsgBuf,
388 0,
389 (va_list*)szArguments) == 0)
390 {
391 /* We haven't found the string, get next DLL (if any) */
392 szDll = wcstok(NULL, EVENT_DLL_SEPARATOR);
393 }
394 else if (lpMsgBuf)
395 {
396 /* The ID was found and the message was formated */
397 Success = TRUE;
398
399 /* Trim the string */
400 TrimNulls((LPWSTR)lpMsgBuf);
401
402 /* Copy the event text */
403 StringCchCopyW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, lpMsgBuf);
404 }
405
406 /* Free the buffer allocated by FormatMessage */
407 if (lpMsgBuf)
408 LocalFree(lpMsgBuf);
409
410 FreeLibrary(hLibrary);
411 }
412
413 HeapFree(GetProcessHeap(), 0, szArguments);
414
415 // Quit:
416 if (!Success)
417 {
418 LoadStringW(hInst, IDS_EVENTSTRINGIDNOTFOUND, szStringIDNotFound, ARRAYSIZE(szStringIDNotFound));
419 StringCchPrintfW(EventText, EVENT_MESSAGE_EVENTTEXT_BUFFER, szStringIDNotFound, (pevlr->EventID & 0xFFFF), SourceName);
420 }
421
422 return Success;
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 = CreateDialogParamW(hInst,
498 MAKEINTRESOURCEW(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 (GetMessageW(&Msg, NULL, 0, 0))
511 {
512 TranslateMessage(&Msg);
513 DispatchMessageW(&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 BOOL bResult = TRUE; /* Read succeeded. */
532
533 WCHAR szWindowTitle[MAX_PATH];
534 WCHAR szStatusText[MAX_PATH];
535 WCHAR szLocalDate[MAX_PATH];
536 WCHAR szLocalTime[MAX_PATH];
537 WCHAR szEventID[MAX_PATH];
538 WCHAR szEventTypeText[MAX_LOADSTRING];
539 WCHAR szCategoryID[MAX_PATH];
540 WCHAR szUsername[MAX_PATH];
541 WCHAR szCategory[MAX_PATH];
542 PWCHAR lpTitleTemplateEnd;
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, lpLogName);
551 if (hEventLog == NULL)
552 {
553 ShowLastWin32Error();
554 return FALSE;
555 }
556
557 lpSourceLogName = lpLogName;
558 lpComputerName = lpMachineName;
559
560 /* Disable listview redraw */
561 SendMessageW(hwndListView, WM_SETREDRAW, FALSE, 0);
562
563 /* Clear the list view */
564 (void)ListView_DeleteAllItems(hwndListView);
565 FreeRecords();
566
567 GetOldestEventLogRecord(hEventLog, &dwThisRecord);
568
569 /* Get the total number of event log records. */
570 GetNumberOfEventLogRecords(hEventLog, &dwTotalRecords);
571 g_TotalRecords = dwTotalRecords;
572
573 if (dwTotalRecords > 0)
574 {
575 EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_ENABLED);
576 EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_ENABLED);
577 }
578 else
579 {
580 EnableMenuItem(hMainMenu, IDM_CLEAR_EVENTS, MF_BYCOMMAND | MF_GRAYED);
581 EnableMenuItem(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_GRAYED);
582 }
583
584 g_RecordPtrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwTotalRecords * sizeof(*g_RecordPtrs));
585
586 /* If we have at least 1000 records show the waiting dialog */
587 if (dwTotalRecords > 1000)
588 {
589 CloseHandle(CreateThread(NULL,
590 0,
591 ShowStatusMessageThread,
592 (LPVOID)&hwndDlg,
593 0,
594 NULL));
595 }
596
597 while (dwCurrentRecord < dwTotalRecords)
598 {
599 pevlr = HeapAlloc(GetProcessHeap(), 0, sizeof(*pevlr));
600 g_RecordPtrs[dwCurrentRecord] = pevlr;
601
602 bResult = ReadEventLogW(hEventLog, // Event log handle
603 dwFlags, // Sequential read
604 0, // Ignored for sequential read
605 pevlr, // Pointer to buffer
606 sizeof(*pevlr), // Size of buffer
607 &dwRead, // Number of bytes read
608 &dwNeeded); // Bytes in the next record
609 if ((!bResult) && (GetLastError () == ERROR_INSUFFICIENT_BUFFER))
610 {
611 HeapFree(GetProcessHeap(), 0, pevlr);
612 pevlr = HeapAlloc(GetProcessHeap(), 0, dwNeeded);
613 g_RecordPtrs[dwCurrentRecord] = pevlr;
614
615 ReadEventLogW(hEventLog, // event log handle
616 dwFlags, // read flags
617 0, // offset; default is 0
618 pevlr, // pointer to buffer
619 dwNeeded, // size of buffer
620 &dwRead, // number of bytes read
621 &dwNeeded); // bytes in next record
622 }
623
624 while (dwRead > 0)
625 {
626 LoadStringW(hInst, IDS_NOT_AVAILABLE, szUsername, ARRAYSIZE(szUsername));
627 LoadStringW(hInst, IDS_NONE, szCategory, ARRAYSIZE(szCategory));
628
629 // Get the event source name.
630 lpSourceName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD));
631
632 // Get the computer name
633 lpComputerName = (LPWSTR)((LPBYTE)pevlr + sizeof(EVENTLOGRECORD) + (wcslen(lpSourceName) + 1) * sizeof(WCHAR));
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, ARRAYSIZE(szLocalDate));
642 GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &time, NULL, szLocalTime, ARRAYSIZE(szLocalTime));
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
693 dwRead -= pevlr->Length;
694 pevlr = (EVENTLOGRECORD *)((LPBYTE) pevlr + pevlr->Length);
695 }
696
697 dwRecordsToRead--;
698 dwCurrentRecord++;
699 }
700
701 // All events loaded
702 if (hwndDlg)
703 EndDialog(hwndDlg, 0);
704
705 StringCchPrintfExW(szWindowTitle,
706 ARRAYSIZE(szWindowTitle),
707 &lpTitleTemplateEnd,
708 &cchRemaining,
709 0,
710 szTitleTemplate, szTitle, lpLogName); /* i = number of characters written */
711 /* lpComputerName can be NULL here if no records was read */
712 dwMaxLength = (DWORD)cchRemaining;
713 if (!lpComputerName)
714 GetComputerNameW(lpTitleTemplateEnd, &dwMaxLength);
715 else
716 StringCchCopyW(lpTitleTemplateEnd, dwMaxLength, lpComputerName);
717
718 StringCbPrintfW(szStatusText, sizeof(szStatusText), szStatusBarTemplate, lpLogName, dwTotalRecords);
719
720 // Update the status bar
721 SendMessageW(hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)szStatusText);
722
723 // Set the window title
724 SetWindowTextW(hwndMainWindow, szWindowTitle);
725
726 // Resume list view redraw
727 SendMessageW(hwndListView, WM_SETREDRAW, TRUE, 0);
728
729 // Close the event log.
730 CloseEventLog(hEventLog);
731
732 return TRUE;
733 }
734
735
736 VOID
737 SaveProtocol(VOID)
738 {
739 HANDLE hEventLog;
740 WCHAR szFileName[MAX_PATH];
741
742 ZeroMemory(szFileName, sizeof(szFileName));
743
744 sfn.lpstrFile = szFileName;
745 sfn.nMaxFile = ARRAYSIZE(szFileName);
746
747 if (!GetSaveFileNameW(&sfn))
748 {
749 return;
750 }
751
752 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
753 if (!hEventLog)
754 {
755 ShowLastWin32Error();
756 return;
757 }
758
759 if (!BackupEventLogW(hEventLog, szFileName))
760 {
761 ShowLastWin32Error();
762 }
763
764 CloseEventLog(hEventLog);
765 }
766
767
768 BOOL
769 ClearEvents(VOID)
770 {
771 HANDLE hEventLog;
772 WCHAR szFileName[MAX_PATH];
773 WCHAR szMessage[MAX_LOADSTRING];
774
775 ZeroMemory(szFileName, sizeof(szFileName));
776 ZeroMemory(szMessage, sizeof(szMessage));
777
778 LoadStringW(hInst, IDS_CLEAREVENTS_MSG, szMessage, ARRAYSIZE(szMessage));
779
780 sfn.lpstrFile = szFileName;
781 sfn.nMaxFile = ARRAYSIZE(szFileName);
782
783 switch (MessageBoxW(hwndMainWindow, szMessage, szTitle, MB_YESNOCANCEL | MB_ICONINFORMATION))
784 {
785 case IDCANCEL:
786 {
787 return FALSE;
788 }
789
790 case IDNO:
791 {
792 sfn.lpstrFile = NULL;
793 break;
794 }
795
796 case IDYES:
797 {
798 if (!GetSaveFileNameW(&sfn))
799 {
800 return FALSE;
801 }
802 break;
803 }
804 }
805
806 hEventLog = OpenEventLogW(lpComputerName, lpSourceLogName);
807 if (!hEventLog)
808 {
809 ShowLastWin32Error();
810 return FALSE;
811 }
812
813 if (!ClearEventLogW(hEventLog, sfn.lpstrFile))
814 {
815 ShowLastWin32Error();
816 CloseEventLog(hEventLog);
817 return FALSE;
818 }
819
820 CloseEventLog(hEventLog);
821
822 return TRUE;
823 }
824
825
826 VOID
827 Refresh(VOID)
828 {
829 QueryEventMessages(lpComputerName,
830 lpSourceLogName);
831 }
832
833
834 ATOM
835 MyRegisterClass(HINSTANCE hInstance)
836 {
837 WNDCLASSEXW wcex;
838
839 wcex.cbSize = sizeof(wcex);
840 wcex.style = 0;
841 wcex.lpfnWndProc = WndProc;
842 wcex.cbClsExtra = 0;
843 wcex.cbWndExtra = 0;
844 wcex.hInstance = hInstance;
845 wcex.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_EVENTVWR));
846 wcex.hCursor = LoadCursorW(NULL, MAKEINTRESOURCEW(IDC_ARROW));
847 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
848 wcex.lpszMenuName = MAKEINTRESOURCEW(IDM_EVENTVWR);
849 wcex.lpszClassName = szWindowClass;
850 wcex.hIconSm = (HICON)LoadImageW(hInstance,
851 MAKEINTRESOURCEW(IDI_EVENTVWR),
852 IMAGE_ICON,
853 16,
854 16,
855 LR_SHARED);
856
857 return RegisterClassExW(&wcex);
858 }
859
860
861 VOID
862 GetDisplayNameFile(IN LPCWSTR lpLogName,
863 OUT PWCHAR lpModuleName)
864 {
865 HKEY hKey;
866 WCHAR *KeyPath;
867 WCHAR szModuleName[MAX_PATH];
868 DWORD cbData;
869 SIZE_T cbKeyPath;
870
871 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
872 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
873 if (!KeyPath)
874 {
875 return;
876 }
877
878 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
879 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
880
881 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
882 {
883 HeapFree(GetProcessHeap(), 0, KeyPath);
884 return;
885 }
886
887 cbData = sizeof(szModuleName);
888 if (RegQueryValueExW(hKey, L"DisplayNameFile", NULL, NULL, (LPBYTE)szModuleName, &cbData) == ERROR_SUCCESS)
889 {
890 ExpandEnvironmentStringsW(szModuleName, lpModuleName, MAX_PATH);
891 }
892
893 RegCloseKey(hKey);
894 HeapFree(GetProcessHeap(), 0, KeyPath);
895 }
896
897
898 DWORD
899 GetDisplayNameID(IN LPCWSTR lpLogName)
900 {
901 HKEY hKey;
902 WCHAR *KeyPath;
903 DWORD dwMessageID = 0;
904 DWORD cbData;
905 SIZE_T cbKeyPath;
906
907 cbKeyPath = (wcslen(EVENTLOG_BASE_KEY) + wcslen(lpLogName) + 1) * sizeof(WCHAR);
908 KeyPath = HeapAlloc(GetProcessHeap(), 0, cbKeyPath);
909 if (!KeyPath)
910 {
911 return 0;
912 }
913
914 StringCbCopyW(KeyPath, cbKeyPath, EVENTLOG_BASE_KEY);
915 StringCbCatW(KeyPath, cbKeyPath, lpLogName);
916
917 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, KeyPath, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
918 {
919 HeapFree(GetProcessHeap(), 0, KeyPath);
920 return 0;
921 }
922
923 cbData = sizeof(dwMessageID);
924 RegQueryValueExW(hKey, L"DisplayNameID", NULL, NULL, (LPBYTE)&dwMessageID, &cbData);
925
926 RegCloseKey(hKey);
927 HeapFree(GetProcessHeap(), 0, KeyPath);
928
929 return dwMessageID;
930 }
931
932
933 VOID
934 BuildLogList(void)
935 {
936 HKEY hKey;
937 DWORD lpcName;
938 DWORD dwIndex;
939 DWORD dwMessageID;
940 DWORD dwMaxKeyLength;
941 WCHAR szModuleName[MAX_PATH];
942 LPWSTR lpDisplayName;
943 HMODULE hLibrary = NULL;
944
945 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, EVENTLOG_BASE_KEY, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
946 {
947 return;
948 }
949
950 if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwNumLogs, &dwMaxKeyLength, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
951 {
952 RegCloseKey(hKey);
953 return;
954 }
955
956 if (!dwNumLogs)
957 {
958 RegCloseKey(hKey);
959 return;
960 }
961
962 LogNames = HeapAlloc(GetProcessHeap(), 0, (dwNumLogs + 1) * sizeof(LPWSTR));
963
964 if (!LogNames)
965 {
966 RegCloseKey(hKey);
967 return;
968 }
969
970 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
971 {
972 LogNames[dwIndex] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ((dwMaxKeyLength + 1) * sizeof(WCHAR)));
973
974 if (LogNames[dwIndex] != NULL)
975 {
976 lpcName = dwMaxKeyLength + 1;
977
978 if (RegEnumKeyExW(hKey, dwIndex, LogNames[dwIndex], &lpcName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
979 {
980 lpDisplayName = NULL;
981
982 ZeroMemory(szModuleName, sizeof(szModuleName));
983 GetDisplayNameFile(LogNames[dwIndex], szModuleName);
984 dwMessageID = GetDisplayNameID(LogNames[dwIndex]);
985
986 hLibrary = LoadLibraryExW(szModuleName, NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
987 if (hLibrary != NULL)
988 {
989 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
990 hLibrary,
991 dwMessageID,
992 0,
993 (LPWSTR)&lpDisplayName,
994 0,
995 NULL);
996 FreeLibrary(hLibrary);
997 }
998
999 if (lpDisplayName)
1000 {
1001 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, lpDisplayName);
1002 }
1003 else
1004 {
1005 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_STRING, ID_FIRST_LOG + dwIndex, LogNames[dwIndex]);
1006 }
1007
1008 /* Free the buffer allocated by FormatMessage */
1009 if (lpDisplayName)
1010 LocalFree(lpDisplayName);
1011 }
1012 }
1013 }
1014
1015 InsertMenuW(hMainMenu, IDM_SAVE_PROTOCOL, MF_BYCOMMAND | MF_SEPARATOR, ID_FIRST_LOG + dwIndex + 1, NULL);
1016
1017 RegCloseKey(hKey);
1018
1019 return;
1020 }
1021
1022
1023 VOID
1024 FreeLogList(void)
1025 {
1026 DWORD dwIndex;
1027
1028 if (!LogNames)
1029 {
1030 return;
1031 }
1032
1033 for (dwIndex = 0; dwIndex < dwNumLogs; dwIndex++)
1034 {
1035 if (LogNames[dwIndex])
1036 {
1037 HeapFree(GetProcessHeap(), 0, LogNames[dwIndex]);
1038 }
1039
1040 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex, MF_BYCOMMAND);
1041 }
1042
1043 DeleteMenu(hMainMenu, ID_FIRST_LOG + dwIndex + 1, MF_BYCOMMAND);
1044
1045 HeapFree(GetProcessHeap(), 0, LogNames);
1046
1047 dwNumLogs = 0;
1048
1049 return;
1050 }
1051
1052
1053 BOOL
1054 InitInstance(HINSTANCE hInstance,
1055 int nCmdShow)
1056 {
1057 HIMAGELIST hSmall;
1058 LVCOLUMNW lvc = {0};
1059 WCHAR szTemp[256];
1060
1061 hInst = hInstance; // Store instance handle in our global variable
1062
1063 hwndMainWindow = CreateWindowW(szWindowClass,
1064 szTitle,
1065 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
1066 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
1067 NULL,
1068 NULL,
1069 hInstance,
1070 NULL);
1071 if (!hwndMainWindow)
1072 {
1073 return FALSE;
1074 }
1075
1076 hwndStatus = CreateWindowExW(0, // no extended styles
1077 STATUSCLASSNAMEW, // status bar
1078 L"", // no text
1079 WS_CHILD | WS_BORDER | WS_VISIBLE, // styles
1080 0, 0, 0, 0, // x, y, cx, cy
1081 hwndMainWindow, // parent window
1082 (HMENU)100, // window ID
1083 hInstance, // instance
1084 NULL); // window data
1085
1086 // Create our listview child window. Note that I use WS_EX_CLIENTEDGE
1087 // and WS_BORDER to create the normal "sunken" look. Also note that
1088 // LVS_EX_ styles cannot be set in CreateWindowEx().
1089 hwndListView = CreateWindowExW(WS_EX_CLIENTEDGE,
1090 WC_LISTVIEWW,
1091 L"",
1092 LVS_SHOWSELALWAYS | WS_CHILD | WS_VISIBLE | LVS_REPORT,
1093 0,
1094 0,
1095 243,
1096 200,
1097 hwndMainWindow,
1098 NULL,
1099 hInstance,
1100 NULL);
1101
1102 // After the ListView is created, we can add extended list view styles.
1103 (void)ListView_SetExtendedListViewStyle (hwndListView, LVS_EX_FULLROWSELECT);
1104
1105 // Create the ImageList
1106 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1107 GetSystemMetrics(SM_CYSMICON),
1108 ILC_COLOR32,
1109 1,
1110 1);
1111
1112 // Add event type icons to ImageList
1113 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_INFORMATIONICON)));
1114 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_WARNINGICON)));
1115 ImageList_AddIcon(hSmall, LoadIconW(hInstance, MAKEINTRESOURCEW(IDI_ERRORICON)));
1116
1117 // Assign ImageList to List View
1118 (void)ListView_SetImageList(hwndListView, hSmall, LVSIL_SMALL);
1119
1120 // Now set up the listview with its columns.
1121 lvc.mask = LVCF_TEXT | LVCF_WIDTH;
1122 lvc.cx = 90;
1123 LoadStringW(hInstance,
1124 IDS_COLUMNTYPE,
1125 szTemp,
1126 ARRAYSIZE(szTemp));
1127 lvc.pszText = szTemp;
1128 (void)ListView_InsertColumn(hwndListView, 0, &lvc);
1129
1130 lvc.cx = 70;
1131 LoadStringW(hInstance,
1132 IDS_COLUMNDATE,
1133 szTemp,
1134 ARRAYSIZE(szTemp));
1135 lvc.pszText = szTemp;
1136 (void)ListView_InsertColumn(hwndListView, 1, &lvc);
1137
1138 lvc.cx = 70;
1139 LoadStringW(hInstance,
1140 IDS_COLUMNTIME,
1141 szTemp,
1142 ARRAYSIZE(szTemp));
1143 lvc.pszText = szTemp;
1144 (void)ListView_InsertColumn(hwndListView, 2, &lvc);
1145
1146 lvc.cx = 150;
1147 LoadStringW(hInstance,
1148 IDS_COLUMNSOURCE,
1149 szTemp,
1150 ARRAYSIZE(szTemp));
1151 lvc.pszText = szTemp;
1152 (void)ListView_InsertColumn(hwndListView, 3, &lvc);
1153
1154 lvc.cx = 100;
1155 LoadStringW(hInstance,
1156 IDS_COLUMNCATEGORY,
1157 szTemp,
1158 ARRAYSIZE(szTemp));
1159 lvc.pszText = szTemp;
1160 (void)ListView_InsertColumn(hwndListView, 4, &lvc);
1161
1162 lvc.cx = 60;
1163 LoadStringW(hInstance,
1164 IDS_COLUMNEVENT,
1165 szTemp,
1166 ARRAYSIZE(szTemp));
1167 lvc.pszText = szTemp;
1168 (void)ListView_InsertColumn(hwndListView, 5, &lvc);
1169
1170 lvc.cx = 120;
1171 LoadStringW(hInstance,
1172 IDS_COLUMNUSER,
1173 szTemp,
1174 ARRAYSIZE(szTemp));
1175 lvc.pszText = szTemp;
1176 (void)ListView_InsertColumn(hwndListView, 6, &lvc);
1177
1178 lvc.cx = 100;
1179 LoadStringW(hInstance,
1180 IDS_COLUMNCOMPUTER,
1181 szTemp,
1182 ARRAYSIZE(szTemp));
1183 lvc.pszText = szTemp;
1184 (void)ListView_InsertColumn(hwndListView, 7, &lvc);
1185
1186 // Initialize the save Dialog
1187 ZeroMemory(&sfn, sizeof(sfn));
1188 ZeroMemory(szSaveFilter, sizeof(szSaveFilter));
1189
1190 LoadStringW(hInst, IDS_SAVE_FILTER, szSaveFilter, ARRAYSIZE(szSaveFilter));
1191
1192 sfn.lStructSize = sizeof(sfn);
1193 sfn.hwndOwner = hwndMainWindow;
1194 sfn.hInstance = hInstance;
1195 sfn.lpstrFilter = szSaveFilter;
1196 sfn.lpstrInitialDir = NULL;
1197 sfn.Flags = OFN_HIDEREADONLY | OFN_SHAREAWARE;
1198 sfn.lpstrDefExt = NULL;
1199
1200 ShowWindow(hwndMainWindow, nCmdShow);
1201 UpdateWindow(hwndMainWindow);
1202
1203 BuildLogList();
1204
1205 QueryEventMessages(lpComputerName, LogNames[0]);
1206
1207 CheckMenuRadioItem(GetMenu(hwndMainWindow), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, ID_FIRST_LOG, MF_BYCOMMAND);
1208
1209 return TRUE;
1210 }
1211
1212
1213 LRESULT CALLBACK
1214 WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1215 {
1216 RECT rect;
1217 NMHDR *hdr;
1218
1219 switch (message)
1220 {
1221 case WM_CREATE:
1222 hMainMenu = GetMenu(hWnd);
1223 break;
1224
1225 case WM_DESTROY:
1226 {
1227 FreeRecords();
1228 FreeLogList();
1229 PostQuitMessage(0);
1230 break;
1231 }
1232
1233 case WM_NOTIFY:
1234 switch (((LPNMHDR)lParam)->code)
1235 {
1236 case NM_DBLCLK:
1237 hdr = (NMHDR FAR*)lParam;
1238 if (hdr->hwndFrom == hwndListView)
1239 {
1240 LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
1241
1242 if (lpnmitem->iItem != -1)
1243 {
1244 DialogBoxW(hInst,
1245 MAKEINTRESOURCEW(IDD_EVENTPROPERTIES),
1246 hWnd,
1247 EventDetails);
1248 }
1249 }
1250 break;
1251 }
1252 break;
1253
1254 case WM_COMMAND:
1255 {
1256 // Parse the menu selections:
1257
1258 if ((LOWORD(wParam) >= ID_FIRST_LOG) && (LOWORD(wParam) <= ID_FIRST_LOG + dwNumLogs))
1259 {
1260 if (LogNames[LOWORD(wParam) - ID_FIRST_LOG])
1261 {
1262 if (QueryEventMessages(lpComputerName, LogNames[LOWORD(wParam) - ID_FIRST_LOG]))
1263 {
1264 CheckMenuRadioItem(GetMenu(hWnd), ID_FIRST_LOG, ID_FIRST_LOG + dwNumLogs, LOWORD(wParam), MF_BYCOMMAND);
1265 }
1266 }
1267 }
1268 else
1269
1270 switch (LOWORD(wParam))
1271 {
1272 case IDM_SAVE_PROTOCOL:
1273 SaveProtocol();
1274 break;
1275
1276 case IDM_CLEAR_EVENTS:
1277 if (ClearEvents())
1278 {
1279 Refresh();
1280 }
1281 break;
1282
1283 case IDM_REFRESH:
1284 Refresh();
1285 break;
1286
1287 case IDM_ABOUT:
1288 DialogBoxW(hInst, MAKEINTRESOURCEW(IDD_ABOUTBOX), hWnd, About);
1289 break;
1290
1291 case IDM_HELP:
1292 MessageBoxW(hwndMainWindow,
1293 L"Help not implemented yet!",
1294 L"Event Log",
1295 MB_OK | MB_ICONINFORMATION);
1296 break;
1297
1298 case IDM_EXIT:
1299 DestroyWindow(hWnd);
1300 break;
1301
1302 default:
1303 return DefWindowProcW(hWnd, message, wParam, lParam);
1304 }
1305 break;
1306 }
1307
1308 case WM_SIZE:
1309 {
1310 // Gets the window rectangle
1311 GetClientRect(hWnd, &rect);
1312
1313 // Relocate the listview
1314 MoveWindow(hwndListView,
1315 0,
1316 0,
1317 rect.right,
1318 rect.bottom - 20,
1319 1);
1320
1321 // Resize the statusbar;
1322 SendMessageW(hwndStatus, message, wParam, lParam);
1323 break;
1324 }
1325
1326 default:
1327 return DefWindowProcW(hWnd, message, wParam, lParam);
1328 }
1329
1330 return 0;
1331 }
1332
1333
1334 // Message handler for about box.
1335 INT_PTR CALLBACK
1336 About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1337 {
1338 UNREFERENCED_PARAMETER(lParam);
1339 switch (message)
1340 {
1341 case WM_INITDIALOG:
1342 {
1343 return (INT_PTR)TRUE;
1344 }
1345
1346 case WM_COMMAND:
1347 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
1348 {
1349 EndDialog(hDlg, LOWORD(wParam));
1350 return (INT_PTR)TRUE;
1351 }
1352 break;
1353 }
1354
1355 return (INT_PTR)FALSE;
1356 }
1357
1358 VOID
1359 DisplayEvent(HWND hDlg)
1360 {
1361 WCHAR szEventType[MAX_PATH];
1362 WCHAR szTime[MAX_PATH];
1363 WCHAR szDate[MAX_PATH];
1364 WCHAR szUser[MAX_PATH];
1365 WCHAR szComputer[MAX_PATH];
1366 WCHAR szSource[MAX_PATH];
1367 WCHAR szCategory[MAX_PATH];
1368 WCHAR szEventID[MAX_PATH];
1369 WCHAR szEventText[EVENT_MESSAGE_EVENTTEXT_BUFFER];
1370 WCHAR szEventData[MAX_PATH];
1371 BOOL bEventData = FALSE;
1372 LVITEMW li;
1373 EVENTLOGRECORD* pevlr;
1374 int iIndex;
1375
1376 // Get index of selected item
1377 iIndex = (int)SendMessageW(hwndListView, LVM_GETNEXTITEM, -1, LVNI_SELECTED | LVNI_FOCUSED);
1378 if (iIndex == -1)
1379 {
1380 MessageBoxW(NULL,
1381 L"No Items in ListView",
1382 L"Error",
1383 MB_OK | MB_ICONINFORMATION);
1384 return;
1385 }
1386
1387 li.mask = LVIF_PARAM;
1388 li.iItem = iIndex;
1389 li.iSubItem = 0;
1390
1391 (void)ListView_GetItem(hwndListView, &li);
1392
1393 pevlr = (EVENTLOGRECORD*)li.lParam;
1394
1395 ListView_GetItemText(hwndListView, iIndex, 0, szEventType, ARRAYSIZE(szEventType));
1396 ListView_GetItemText(hwndListView, iIndex, 1, szDate, ARRAYSIZE(szDate));
1397 ListView_GetItemText(hwndListView, iIndex, 2, szTime, ARRAYSIZE(szTime));
1398 ListView_GetItemText(hwndListView, iIndex, 3, szSource, ARRAYSIZE(szSource));
1399 ListView_GetItemText(hwndListView, iIndex, 4, szCategory, ARRAYSIZE(szCategory));
1400 ListView_GetItemText(hwndListView, iIndex, 5, szEventID, ARRAYSIZE(szEventID));
1401 ListView_GetItemText(hwndListView, iIndex, 6, szUser, ARRAYSIZE(szUser));
1402 ListView_GetItemText(hwndListView, iIndex, 7, szComputer, ARRAYSIZE(szComputer));
1403
1404 SetDlgItemTextW(hDlg, IDC_EVENTDATESTATIC, szDate);
1405 SetDlgItemTextW(hDlg, IDC_EVENTTIMESTATIC, szTime);
1406 SetDlgItemTextW(hDlg, IDC_EVENTUSERSTATIC, szUser);
1407 SetDlgItemTextW(hDlg, IDC_EVENTSOURCESTATIC, szSource);
1408 SetDlgItemTextW(hDlg, IDC_EVENTCOMPUTERSTATIC, szComputer);
1409 SetDlgItemTextW(hDlg, IDC_EVENTCATEGORYSTATIC, szCategory);
1410 SetDlgItemTextW(hDlg, IDC_EVENTIDSTATIC, szEventID);
1411 SetDlgItemTextW(hDlg, IDC_EVENTTYPESTATIC, szEventType);
1412
1413 bEventData = (pevlr->DataLength > 0);
1414 if (bEventData)
1415 {
1416 // This is the data section of the current event
1417 MultiByteToWideChar(CP_ACP,
1418 0,
1419 (LPCSTR)((LPBYTE)pevlr + pevlr->DataOffset),
1420 pevlr->DataLength,
1421 szEventData,
1422 MAX_PATH);
1423
1424 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, szEventData);
1425 }
1426 else
1427 {
1428 SetDlgItemTextW(hDlg, IDC_EVENTDATAEDIT, L"");
1429 }
1430 EnableWindow(GetDlgItem(hDlg, IDC_BYTESRADIO), bEventData);
1431 EnableWindow(GetDlgItem(hDlg, IDC_WORDRADIO), bEventData);
1432
1433 GetEventMessage(lpSourceLogName, szSource, pevlr, szEventText);
1434 SetDlgItemTextW(hDlg, IDC_EVENTTEXTEDIT, szEventText);
1435 }
1436
1437 VOID
1438 CopyEventEntry(HWND hWnd)
1439 {
1440 WCHAR output[4130], tmpHeader[512];
1441 WCHAR szEventType[MAX_PATH];
1442 WCHAR szSource[MAX_PATH];
1443 WCHAR szCategory[MAX_PATH];
1444 WCHAR szEventID[MAX_PATH];
1445 WCHAR szDate[MAX_PATH];
1446 WCHAR szTime[MAX_PATH];
1447 WCHAR szUser[MAX_PATH];
1448 WCHAR szComputer[MAX_PATH];
1449 WCHAR evtDesc[ENTRY_SIZE];
1450 HGLOBAL hMem;
1451
1452 if (!OpenClipboard(hWnd))
1453 return;
1454
1455 /* First, empty the clipboard before we begin to use it */
1456 EmptyClipboard();
1457
1458 /* Get the formatted text needed to place the content into */
1459 LoadStringW(hInst, IDS_COPY, tmpHeader, ARRAYSIZE(tmpHeader));
1460
1461 /* Grabs all the information and get it ready for the clipboard */
1462 GetDlgItemTextW(hWnd, IDC_EVENTTYPESTATIC, szEventType, ARRAYSIZE(szEventType));
1463 GetDlgItemTextW(hWnd, IDC_EVENTSOURCESTATIC, szSource, ARRAYSIZE(szSource));
1464 GetDlgItemTextW(hWnd, IDC_EVENTCATEGORYSTATIC, szCategory, ARRAYSIZE(szCategory));
1465 GetDlgItemTextW(hWnd, IDC_EVENTIDSTATIC, szEventID, ARRAYSIZE(szEventID));
1466 GetDlgItemTextW(hWnd, IDC_EVENTDATESTATIC, szDate, ARRAYSIZE(szDate));
1467 GetDlgItemTextW(hWnd, IDC_EVENTTIMESTATIC, szTime, ARRAYSIZE(szTime));
1468 GetDlgItemTextW(hWnd, IDC_EVENTUSERSTATIC, szUser, ARRAYSIZE(szUser));
1469 GetDlgItemTextW(hWnd, IDC_EVENTCOMPUTERSTATIC, szComputer, ARRAYSIZE(szComputer));
1470 GetDlgItemTextW(hWnd, IDC_EVENTTEXTEDIT, evtDesc, ARRAYSIZE(evtDesc));
1471
1472 /* Consolidate the information into on big piece */
1473 wsprintfW(output, tmpHeader, szEventType, szSource, szCategory, szEventID, szDate, szTime, szUser, szComputer, evtDesc);
1474
1475 /* Sort out the memory needed to write to the clipboard */
1476 hMem = GlobalAlloc(GMEM_MOVEABLE, ENTRY_SIZE);
1477 memcpy(GlobalLock(hMem), output, ENTRY_SIZE);
1478 GlobalUnlock(hMem);
1479
1480 /* Write the final content to the clipboard */
1481 SetClipboardData(CF_UNICODETEXT, hMem);
1482
1483 /* Close the clipboard once we're done with it */
1484 CloseClipboard();
1485 }
1486
1487 static
1488 INT_PTR CALLBACK
1489 StatusMessageWindowProc(IN HWND hwndDlg,
1490 IN UINT uMsg,
1491 IN WPARAM wParam,
1492 IN LPARAM lParam)
1493 {
1494 UNREFERENCED_PARAMETER(hwndDlg);
1495 UNREFERENCED_PARAMETER(wParam);
1496 UNREFERENCED_PARAMETER(lParam);
1497
1498 switch (uMsg)
1499 {
1500 case WM_INITDIALOG:
1501 return TRUE;
1502 }
1503 return FALSE;
1504 }
1505
1506 static
1507 VOID
1508 InitDetailsDlg(HWND hDlg)
1509 {
1510 HANDLE nextIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_NEXT), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1511 HANDLE prevIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_PREV), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1512 HANDLE copyIcon = LoadImageW(hInst, MAKEINTRESOURCEW(IDI_COPY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
1513
1514 SendMessageW(GetDlgItem(hDlg, IDC_NEXT), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)nextIcon);
1515 SendMessageW(GetDlgItem(hDlg, IDC_PREVIOUS), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)prevIcon);
1516 SendMessageW(GetDlgItem(hDlg, IDC_COPY), BM_SETIMAGE, (WPARAM)IMAGE_ICON, (LPARAM)copyIcon);
1517 }
1518
1519 // Message handler for event details box.
1520 INT_PTR CALLBACK
1521 EventDetails(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
1522 {
1523 UNREFERENCED_PARAMETER(lParam);
1524
1525 switch (message)
1526 {
1527 case WM_INITDIALOG:
1528 {
1529 InitDetailsDlg(hDlg);
1530
1531 // Show event info on dialog box
1532 DisplayEvent(hDlg);
1533 return (INT_PTR)TRUE;
1534 }
1535
1536 case WM_COMMAND:
1537 switch (LOWORD(wParam))
1538 {
1539 case IDOK:
1540 case IDCANCEL:
1541 EndDialog(hDlg, LOWORD(wParam));
1542 return (INT_PTR)TRUE;
1543
1544 case IDC_PREVIOUS:
1545 {
1546 SendMessageW(hwndListView, WM_KEYDOWN, VK_UP, 0);
1547
1548 // Show event info on dialog box
1549 DisplayEvent(hDlg);
1550 return (INT_PTR)TRUE;
1551 }
1552
1553 case IDC_NEXT:
1554 {
1555 SendMessageW(hwndListView, WM_KEYDOWN, VK_DOWN, 0);
1556
1557 // Show event info on dialog box
1558 DisplayEvent(hDlg);
1559 return (INT_PTR)TRUE;
1560 }
1561
1562 case IDC_COPY:
1563 CopyEventEntry(hDlg);
1564 return (INT_PTR)TRUE;
1565
1566 // UNIMPLEMENTED!
1567 case IDC_BYTESRADIO:
1568 return (INT_PTR)TRUE;
1569
1570 // UNIMPLEMENTED!
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 }