[Bug Report Tool] Report event viewer logs (#11458)

This commit is contained in:
Mykhailo Pylyp 2021-05-26 16:23:49 +03:00 committed by GitHub
parent 208e1701d0
commit 0b13c4d6a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 285 additions and 0 deletions

View file

@ -541,6 +541,7 @@ EUQ
evenodd
eventlog
everytime
evt
EWXFORCE
EWXFORCEIFHUNG
EWXLOGOFF
@ -954,6 +955,7 @@ IVector
IView
IVirtual
IWeb
IXml
ixx
IZone
IZoom
@ -1785,6 +1787,7 @@ sln
SMALLICON
SMTO
snd
snwprintf
softline
somil
Soref
@ -1944,6 +1947,7 @@ THISCOMPONENT
thre
tif
TILEDWINDOW
timediff
TIMERID
timeunion
timeutil
@ -2127,6 +2131,7 @@ webpack
webpage
website
wekyb
Wevtapi
Whichdoes
whitespaces
WIC
@ -2156,6 +2161,7 @@ windowwalker
winerror
WINEVENT
winexe
winevt
winforms
winfx
winget

View file

@ -30,15 +30,18 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>Wevtapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\deps\cziplib\src\zip.c">
<WarningLevel>TurnOffAllWarnings</WarningLevel>
</ClCompile>
<ClCompile Include="EventViewer.cpp" />
<ClCompile Include="ReportMonitorInfo.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="RegistryUtils.cpp" />
<ClCompile Include="XmlDocumentEx.cpp" />
<ClCompile Include="ZipTools\ZipFolder.cpp" />
</ItemGroup>
<ItemGroup>
@ -52,9 +55,11 @@
<ItemGroup>
<ClInclude Include="..\..\..\deps\cziplib\src\miniz.h" />
<ClInclude Include="..\..\..\deps\cziplib\src\zip.h" />
<ClInclude Include="EventViewer.h" />
<ClInclude Include="ReportMonitorInfo.h" />
<ClInclude Include="..\..\..\common\utils\json.h" />
<ClInclude Include="RegistryUtils.h" />
<ClInclude Include="XmlDocumentEx.h" />
<ClInclude Include="ZipTools\ZipFolder.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -11,6 +11,8 @@
<ClCompile Include="..\..\..\deps\cziplib\src\zip.c" />
<ClCompile Include="ReportMonitorInfo.cpp" />
<ClCompile Include="RegistryUtils.cpp" />
<ClCompile Include="EventViewer.cpp" />
<ClCompile Include="XmlDocumentEx.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="ZipTools">
@ -26,5 +28,7 @@
<ClInclude Include="..\..\..\deps\cziplib\src\zip.h" />
<ClInclude Include="ReportMonitorInfo.h" />
<ClInclude Include="RegistryUtils.h" />
<ClInclude Include="EventViewer.h" />
<ClInclude Include="XmlDocumentEx.h" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,189 @@
#include "EventViewer.h"
#include <windows.h>
#include <sddl.h>
#include <stdio.h>
#include <winevt.h>
#include <fstream>
#include <common/utils/winapi_error.h>
#include "XmlDocumentEx.h"
namespace
{
std::vector<std::wstring> processes =
{
L"PowerToys.exe",
L"ColorPickerUI.exe",
L"PowerToys.Espresso.exe"
L"FancyZonesEditor.exe",
L"PowerToys.KeyboardManagerEngine.exe",
L"PowerToys.KeyboardManagerEditor.exe",
L"PowerLauncher.exe",
L"PowerToys.ShortcutGuide.exe"
};
// Batch size for number of events queried at once
constexpr int BATCH_SIZE = 50;
class EventViewerReporter
{
private:
// Report last 30 days
const long long PERIOD = 10 * 24 * 3600ll * 1000;
const std::wstring QUERY = L"<QueryList>" \
L" <Query Id='0'>" \
L" <Select Path='Application'>" \
L" *[System[TimeCreated[timediff(@SystemTime)&lt;%I64u]]] " \
L" and *[EventData[Data and (Data='%s')]]" \
L" </Select>" \
L" </Query>" \
L"</QueryList>";
std::wstring GetQuery(std::wstring processName)
{
wchar_t buff[1000];
memset(buff, 0, sizeof(buff));
_snwprintf_s(buff, sizeof(buff), QUERY.c_str(), PERIOD, processName.c_str());
return buff;
}
std::wofstream report;
EVT_HANDLE hResults;
void PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwBufferUsed = 0;
DWORD dwPropertyCount = 0;
LPWSTR pRenderedContent = NULL;
// The EvtRenderEventXml flag tells EvtRender to render the event as an XML string.
if (!EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
pRenderedContent = (LPWSTR)malloc(dwBufferSize);
if (pRenderedContent)
{
EvtRender(NULL, hEvent, EvtRenderEventXml, dwBufferSize, pRenderedContent, &dwBufferUsed, &dwPropertyCount);
}
}
if (ERROR_SUCCESS != (status = GetLastError()))
{
report << std::endl << L"EvtRender failed with " << get_last_error_or_default(GetLastError()) << std::endl << std::endl;
if (pRenderedContent)
{
free(pRenderedContent);
}
return;
}
}
XmlDocumentEx doc;
doc.LoadXml(pRenderedContent);
std::wstring formattedXml = L"";
try
{
formattedXml = doc.GetFormatedXml();
}
catch (...)
{
formattedXml = pRenderedContent;
}
report << std::endl << formattedXml << std::endl;
if (pRenderedContent)
{
free(pRenderedContent);
}
}
// Enumerate all the events in the result set.
void PrintResults(EVT_HANDLE hResults)
{
DWORD status = ERROR_SUCCESS;
EVT_HANDLE hEvents[BATCH_SIZE];
DWORD dwReturned = 0;
while (true)
{
// Get a block of events from the result set.
if (!EvtNext(hResults, BATCH_SIZE, hEvents, INFINITE, 0, &dwReturned))
{
if (ERROR_NO_MORE_ITEMS != (status = GetLastError()))
{
report << L"EvtNext failed with " << status << std::endl;
}
break;
}
// For each event, call the PrintEvent function which renders the
// event for display. PrintEvent is shown in RenderingEvents.
for (DWORD i = 0; i < dwReturned; i++)
{
PrintEvent(hEvents[i]);
}
}
for (DWORD i = 0; i < dwReturned; i++)
{
if (nullptr != hEvents[i])
EvtClose(hEvents[i]);
}
}
public:
EventViewerReporter(const std::filesystem::path& tmpDir, std::wstring processName)
{
auto query = GetQuery(processName);
auto reportPath = tmpDir;
reportPath.append(L"EventViewer-" + processName + L".xml");
report = std::wofstream(reportPath);
hResults = EvtQuery(NULL, NULL, GetQuery(processName).c_str(), EvtQueryChannelPath);
if (NULL == hResults)
{
report << "Failed to report info for " << processName << ". " << get_last_error_or_default(GetLastError()) << std::endl;
return;
}
}
~EventViewerReporter()
{
if (hResults)
{
EvtClose(hResults);
hResults = nullptr;
}
}
void Report()
{
try
{
if (hResults)
{
PrintResults(hResults);
}
}
catch (...)
{
report << "Failed to report info" << std::endl;
}
}
};
}
void EventViewer::ReportEventViewerInfo(const std::filesystem::path& tmpDir)
{
for (auto& process : processes)
{
EventViewerReporter(tmpDir, process).Report();
}
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <filesystem>
namespace EventViewer
{
void ReportEventViewerInfo(const std::filesystem::path& tmpDir);
}

View file

@ -16,6 +16,8 @@
#include "ReportMonitorInfo.h"
#include "RegistryUtils.h"
#include "EventViewer.h"
using namespace std;
using namespace std::filesystem;
using namespace winrt::Windows::Data::Json;
@ -331,6 +333,9 @@ int wmain(int argc, wchar_t* argv[], wchar_t*)
// Write compatibility tab info to the temporary folder
ReportCompatibilityTab(tmpDir);
// Write event viewer logs info to the temporary folder
EventViewer::ReportEventViewerInfo(tmpDir);
ReportBootstrapperLog(tmpDir);
// Zip folder

View file

@ -0,0 +1,56 @@
#include "XmlDocumentEx.h"
#include <winrt/Windows.Foundation.Collections.h>
std::wstring XmlDocumentEx::GetFormatedXml()
{
stream.clear();
Print(FirstChild(), 0);
return stream.str();
}
void XmlDocumentEx::Print(winrt::Windows::Data::Xml::Dom::IXmlNode node, int indentation)
{
for (int i = 0; i < indentation; i++)
{
stream << " ";
}
PrintTagWithAttributes(node);
if (!node.HasChildNodes())
{
stream << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
return;
}
if (node.ChildNodes().Size() == 1 && !node.FirstChild().HasChildNodes())
{
stream << node.InnerText().c_str() << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
return;
}
stream << std::endl;
auto child = node.FirstChild();
do
{
Print(child, indentation + 2);
} while (child = child.NextSibling());
for (int i = 0; i < indentation; i++)
{
stream << " ";
}
stream << L"<\\" << node.NodeName().c_str() << ">" << std::endl;
}
void XmlDocumentEx::PrintTagWithAttributes(winrt::Windows::Data::Xml::Dom::IXmlNode node)
{
stream << L"<" << node.NodeName().c_str();
for (int i = 0; i < (int)node.Attributes().Size(); i++)
{
auto attr = node.Attributes().GetAt(i);
stream << L" " << attr.NodeName().c_str() << L"='" << attr.InnerText().c_str() << L"'";
}
stream << L">";
}

View file

@ -0,0 +1,13 @@
#pragma once
#include <winrt/Windows.Data.Xml.Dom.h>
class XmlDocumentEx : public winrt::Windows::Data::Xml::Dom::XmlDocument
{
private:
std::wstringstream stream;
void Print(winrt::Windows::Data::Xml::Dom::IXmlNode node, int indentation);
void PrintTagWithAttributes(winrt::Windows::Data::Xml::Dom::IXmlNode node);
public:
std::wstring GetFormatedXml();
};