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