chore: import upstream snapshot with attribution
Spell checking / Check Spelling (push) Has been cancelled
Spell checking / Update PR (push) Has been cancelled
Publish Dev Docs Website / build (push) Failing after 1s
Publish Dev Docs Website / deploy (push) Has been skipped
Spell checking / Report (Push) (push) Has been cancelled
Spell checking / Report (PR) (push) Has been cancelled
Spell checking / Check Spelling (push) Has been cancelled
Spell checking / Update PR (push) Has been cancelled
Publish Dev Docs Website / build (push) Failing after 1s
Publish Dev Docs Website / deploy (push) Has been skipped
Spell checking / Report (Push) (push) Has been cancelled
Spell checking / Report (PR) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.32014.148
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BugReportTool", "BugReportTool\BugReportTool.vcxproj", "{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SettingsAPI", "..\..\src\common\SettingsAPI\SettingsAPI.vcxproj", "{6955446D-23F7-4023-9BB3-8657F904AF99}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Debug|x64.Build.0 = Debug|x64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Release|x64.ActiveCfg = Release|x64
|
||||
{99126840-5C30-4E9E-AC6C-E73DDED5C3BD}.Release|x64.Build.0 = Release|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64
|
||||
{6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E9F52385-ED21-4F66-9DA4-F4A2749D480D}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../src/common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
1 VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset
|
||||
END
|
||||
END
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{99126840-5c30-4e9e-ac6c-e73dded5c3bd}</ProjectGuid>
|
||||
<RootNamespace>BugReportTool</RootNamespace>
|
||||
<ProjectName>BugReportTool</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<TargetName>PowerToys.$(ProjectName)</TargetName>
|
||||
<OutDir>$(RepoRoot)$(Platform)\$(Configuration)\Tools\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>../../../src/</AdditionalIncludeDirectories>
|
||||
<TreatAngleIncludeAsExternal>true</TreatAngleIncludeAsExternal>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<AdditionalDependencies>Version.lib;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="EventViewer.cpp" />
|
||||
<ClCompile Include="InstallationFolder.cpp" />
|
||||
<ClCompile Include="Package.cpp" />
|
||||
<ClCompile Include="ProcessesList.cpp" />
|
||||
<ClCompile Include="ReportGPOValues.cpp" />
|
||||
<ClCompile Include="ReportMonitorInfo.cpp" />
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="RegistryUtils.cpp" />
|
||||
<ClCompile Include="XmlDocumentEx.cpp" />
|
||||
<ClCompile Include="ZipTools\ZipFolder.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="EventViewer.h" />
|
||||
<ClInclude Include="InstallationFolder.h" />
|
||||
<ClInclude Include="Package.h" />
|
||||
<ClInclude Include="ReportGPOValues.h" />
|
||||
<ClInclude Include="ReportMonitorInfo.h" />
|
||||
<ClInclude Include="$(RepoRoot)src\common\utils\json.h" />
|
||||
<ClInclude Include="RegistryUtils.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="XmlDocumentEx.h" />
|
||||
<ClInclude Include="ZipTools\ZipFolder.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="BugReportTool.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.ImplementationLibrary.1.0.260126.7\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.CppWinRT.2.0.250303.1\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
<ClCompile Include="ZipTools\ZipFolder.cpp">
|
||||
<Filter>ZipTools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ReportMonitorInfo.cpp" />
|
||||
<ClCompile Include="RegistryUtils.cpp" />
|
||||
<ClCompile Include="EventViewer.cpp" />
|
||||
<ClCompile Include="XmlDocumentEx.cpp" />
|
||||
<ClCompile Include="InstallationFolder.cpp" />
|
||||
<ClCompile Include="ProcessesList.cpp" />
|
||||
<ClCompile Include="Package.cpp" />
|
||||
<ClCompile Include="ReportGPOValues.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="ZipTools">
|
||||
<UniqueIdentifier>{3ae1b6aa-4134-47b1-afdf-dfb3b5901dcc}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ZipTools\ZipFolder.h">
|
||||
<Filter>ZipTools</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\common\utils\json.h" />
|
||||
<ClInclude Include="ReportMonitorInfo.h" />
|
||||
<ClInclude Include="RegistryUtils.h" />
|
||||
<ClInclude Include="EventViewer.h" />
|
||||
<ClInclude Include="XmlDocumentEx.h" />
|
||||
<ClInclude Include="InstallationFolder.h" />
|
||||
<ClInclude Include="Package.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="ReportGPOValues.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="BugReportTool.rc" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,236 @@
|
||||
#include "EventViewer.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <sddl.h>
|
||||
#include <stdio.h>
|
||||
#include <winevt.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
#include "XmlDocumentEx.h"
|
||||
|
||||
extern std::vector<std::wstring> processes;
|
||||
|
||||
namespace
|
||||
{
|
||||
// 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_BY_PROCESS = L"<QueryList>" \
|
||||
L" <Query Id='0'>" \
|
||||
L" <Select Path='Application'>" \
|
||||
L" *[System[TimeCreated[timediff(@SystemTime)<%I64u]]] " \
|
||||
L" and *[EventData[Data and (Data='%s')]]" \
|
||||
L" </Select>" \
|
||||
L" </Query>" \
|
||||
L"</QueryList>";
|
||||
|
||||
const std::wstring QUERY_BY_CHANNEL = L"<QueryList>" \
|
||||
L" <Query Id='0'>" \
|
||||
L" <Select Path='%s'>" \
|
||||
L" *[System[TimeCreated[timediff(@SystemTime)<%I64u]]]" \
|
||||
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_BY_PROCESS.c_str(), PERIOD, processName.c_str());
|
||||
return buff;
|
||||
}
|
||||
|
||||
std::wstring GetQueryByChannel(std::wstring channelName)
|
||||
{
|
||||
wchar_t buff[1000];
|
||||
memset(buff, 0, sizeof(buff));
|
||||
_snwprintf_s(buff, sizeof(buff), QUERY_BY_CHANNEL.c_str(), channelName.c_str(), PERIOD);
|
||||
return buff;
|
||||
}
|
||||
|
||||
std::wofstream report;
|
||||
EVT_HANDLE hResults;
|
||||
bool isChannel;
|
||||
|
||||
bool ShouldIncludeEvent(const std::wstring& eventXml)
|
||||
{
|
||||
if (!isChannel)
|
||||
{
|
||||
return true; // Include all events if no filtering
|
||||
}
|
||||
|
||||
// Check if the event contains PowerToys or CommandPalette
|
||||
return (eventXml.find(L"PowerToys") != std::wstring::npos ||
|
||||
eventXml.find(L"CommandPalette") != std::wstring::npos);
|
||||
}
|
||||
|
||||
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 = static_cast<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;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply filtering if needed
|
||||
std::wstring eventContent(pRenderedContent);
|
||||
if (!ShouldIncludeEvent(eventContent))
|
||||
{
|
||||
if (pRenderedContent)
|
||||
{
|
||||
free(pRenderedContent);
|
||||
}
|
||||
return; // Skip this event
|
||||
}
|
||||
|
||||
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 results)
|
||||
{
|
||||
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(results, 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 queryName, std::wstring fileName, bool isChannel)
|
||||
:isChannel(isChannel)
|
||||
{
|
||||
std::wstring query = L"";
|
||||
if (isChannel)
|
||||
{
|
||||
query = GetQueryByChannel(queryName);
|
||||
}
|
||||
else
|
||||
{
|
||||
query = GetQuery(queryName);
|
||||
}
|
||||
|
||||
auto reportPath = tmpDir;
|
||||
reportPath.append(L"EventViewer-" + fileName + L".xml");
|
||||
report = std::wofstream(reportPath);
|
||||
|
||||
hResults = EvtQuery(NULL, NULL, query.c_str(), EvtQueryChannelPath);
|
||||
if (NULL == hResults)
|
||||
{
|
||||
report << "Failed to report info for " << queryName << ". " << 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, process, false).Report();
|
||||
}
|
||||
}
|
||||
|
||||
void EventViewer::ReportAppXDeploymentLogs(const std::filesystem::path& tmpDir)
|
||||
{
|
||||
EventViewerReporter(tmpDir, L"Microsoft-Windows-AppXDeploymentServer/Operational", L"AppXDeploymentServerEventLog", true).Report();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
|
||||
namespace EventViewer
|
||||
{
|
||||
void ReportEventViewerInfo(const std::filesystem::path& tmpDir);
|
||||
void ReportAppXDeploymentLogs(const std::filesystem::path& tmpDir);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
#include "InstallationFolder.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
#include <Windows.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
using namespace std;
|
||||
using std::filesystem::directory_iterator;
|
||||
using std::filesystem::path;
|
||||
|
||||
wstring GetVersion(path filePath)
|
||||
{
|
||||
DWORD verHandle = 0;
|
||||
UINT size = 0;
|
||||
LPVOID lpBuffer = nullptr;
|
||||
DWORD verSize = GetFileVersionInfoSize(filePath.c_str(), &verHandle);
|
||||
wstring version = L"None";
|
||||
|
||||
if (verSize != 0)
|
||||
{
|
||||
LPSTR verData = new char[verSize];
|
||||
|
||||
if (GetFileVersionInfo(filePath.c_str(), verHandle, verSize, verData))
|
||||
{
|
||||
if (VerQueryValue(verData, L"\\", &lpBuffer, &size))
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
VS_FIXEDFILEINFO* verInfo = static_cast<VS_FIXEDFILEINFO*>(lpBuffer);
|
||||
if (verInfo->dwSignature == 0xfeef04bd)
|
||||
{
|
||||
version =
|
||||
std::to_wstring((verInfo->dwFileVersionMS >> 16) & 0xffff) + L"." +
|
||||
std::to_wstring((verInfo->dwFileVersionMS >> 0) & 0xffff) + L"." +
|
||||
std::to_wstring((verInfo->dwFileVersionLS >> 16) & 0xffff) + L"." +
|
||||
std::to_wstring((verInfo->dwFileVersionLS >> 0) & 0xffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] verData;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
optional<path> GetRootPath()
|
||||
{
|
||||
WCHAR modulePath[MAX_PATH];
|
||||
if (!GetModuleFileName(NULL, modulePath, MAX_PATH))
|
||||
{
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
path rootPath = path(modulePath);
|
||||
rootPath = rootPath.remove_filename();
|
||||
rootPath = rootPath.append("..");
|
||||
return std::filesystem::canonical(rootPath);
|
||||
}
|
||||
|
||||
wstring GetChecksum(path filePath)
|
||||
{
|
||||
BOOL bResult = FALSE;
|
||||
HCRYPTPROV hProv = 0;
|
||||
HCRYPTHASH hHash = 0;
|
||||
HANDLE hFile = NULL;
|
||||
constexpr int bufferSize = 1024;
|
||||
BYTE rgbFile[bufferSize];
|
||||
DWORD cbRead = 0;
|
||||
constexpr int md5Length = 16;
|
||||
BYTE rgbHash[md5Length];
|
||||
DWORD cbHash = 0;
|
||||
CHAR rgbDigits[] = "0123456789abcdef";
|
||||
LPCWSTR filename = filePath.c_str();
|
||||
hFile = CreateFile(filename,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_SEQUENTIAL_SCAN,
|
||||
NULL);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == hFile)
|
||||
{
|
||||
return L"CreateFile() failed. " + get_last_error_or_default(GetLastError());
|
||||
}
|
||||
|
||||
// Get handle to the crypto provider
|
||||
if (!CryptAcquireContext(&hProv,
|
||||
NULL,
|
||||
NULL,
|
||||
PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
return L"CryptAcquireContext() failed. " + get_last_error_or_default(GetLastError());
|
||||
}
|
||||
|
||||
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
CryptReleaseContext(hProv, 0);
|
||||
return L"CryptCreateHash() failed. " + get_last_error_or_default(GetLastError());
|
||||
}
|
||||
|
||||
bResult = ReadFile(hFile, rgbFile, bufferSize, &cbRead, NULL);
|
||||
while (bResult)
|
||||
{
|
||||
if (0 == cbRead)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!CryptHashData(hHash, rgbFile, cbRead, 0))
|
||||
{
|
||||
CryptReleaseContext(hProv, 0);
|
||||
CryptDestroyHash(hHash);
|
||||
CloseHandle(hFile);
|
||||
return L"CryptHashData() failed. " + get_last_error_or_default(GetLastError());;
|
||||
}
|
||||
|
||||
bResult = ReadFile(hFile, rgbFile, bufferSize, &cbRead, NULL);
|
||||
}
|
||||
|
||||
if (!bResult)
|
||||
{
|
||||
CryptReleaseContext(hProv, 0);
|
||||
CryptDestroyHash(hHash);
|
||||
CloseHandle(hFile);
|
||||
return L"ReadFile() failed. " + get_last_error_or_default(GetLastError());;
|
||||
}
|
||||
|
||||
cbHash = md5Length;
|
||||
std::wstring result = L"";
|
||||
if (CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0))
|
||||
{
|
||||
for (DWORD i = 0; i < cbHash; i++)
|
||||
{
|
||||
result += rgbDigits[rgbHash[i] >> 4];
|
||||
result += rgbDigits[rgbHash[i] & 0xf];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = L"CryptGetHashParam() failed. " + get_last_error_or_default(GetLastError());;
|
||||
}
|
||||
|
||||
CryptDestroyHash(hHash);
|
||||
CryptReleaseContext(hProv, 0);
|
||||
CloseHandle(hFile);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
class Reporter
|
||||
{
|
||||
private:
|
||||
std::wofstream os;
|
||||
std::wofstream GetOutputStream(const path& tmpDir)
|
||||
{
|
||||
auto path = tmpDir;
|
||||
path += "installationFolderStructure.txt";
|
||||
std::wofstream out_s = std::wofstream(path);
|
||||
return out_s;
|
||||
}
|
||||
public:
|
||||
Reporter(const path& tmpDir)
|
||||
{
|
||||
os = GetOutputStream(tmpDir);
|
||||
}
|
||||
|
||||
void Report(path dirPath, int indentation = 0)
|
||||
{
|
||||
set<pair<path, bool>> paths;
|
||||
try
|
||||
{
|
||||
directory_iterator end_it;
|
||||
for (directory_iterator it(dirPath); it != end_it; ++it)
|
||||
{
|
||||
paths.insert({ it->path(), it->is_directory() });
|
||||
}
|
||||
}
|
||||
catch (filesystem::filesystem_error err)
|
||||
{
|
||||
os << err.what() << endl;
|
||||
}
|
||||
|
||||
for (auto filePair : paths)
|
||||
{
|
||||
auto filePath = filePair.first;
|
||||
auto isDirectory = filePair.second;
|
||||
|
||||
auto fileName = filePath.wstring().substr(dirPath.wstring().size() + 1);
|
||||
os << wstring(indentation, ' ') << fileName << " ";
|
||||
if (!isDirectory)
|
||||
{
|
||||
os << GetVersion(filePath) << " " << GetChecksum(filePath);
|
||||
}
|
||||
|
||||
os << endl;
|
||||
if (isDirectory)
|
||||
{
|
||||
Report(filePath, indentation + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void InstallationFolder::ReportStructure(const path& tmpDir)
|
||||
{
|
||||
auto rootPath = GetRootPath();
|
||||
if (rootPath)
|
||||
{
|
||||
Reporter(tmpDir).Report(rootPath.value());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
|
||||
namespace InstallationFolder
|
||||
{
|
||||
void ReportStructure(const std::filesystem::path& tmpDir);
|
||||
};
|
||||
@@ -0,0 +1,406 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <Shlobj.h>
|
||||
#include <winrt/Windows.Data.Json.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.System.UserProfile.h>
|
||||
#include <winrt/Windows.Globalization.h>
|
||||
|
||||
#include "ZipTools/ZipFolder.h"
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/utils/json.h>
|
||||
#include <common/utils/timeutil.h>
|
||||
#include <common/utils/exec.h>
|
||||
|
||||
#include "Package.h"
|
||||
#include "ReportMonitorInfo.h"
|
||||
#include "RegistryUtils.h"
|
||||
#include "EventViewer.h"
|
||||
#include "InstallationFolder.h"
|
||||
#include "ReportGPOValues.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace std::filesystem;
|
||||
using namespace winrt::Windows::Data::Json;
|
||||
|
||||
map<wstring, vector<wstring>> escapeInfo = {
|
||||
{ L"FancyZones\\app-zone-history.json", { L"app-zone-history/app-path" } },
|
||||
{ L"FancyZones\\settings.json", { L"properties/fancyzones_excluded_apps" } },
|
||||
{ L"MouseWithoutBorders\\settings.json", { L"properties/SecurityKey" } }, // avoid leaking connection key
|
||||
{ L"Keyboard Manager\\default.json", {
|
||||
L"remapKeysToText",
|
||||
L"remapShortcutsToText",
|
||||
L"remapShortcuts/global/runProgramFilePath",
|
||||
L"remapShortcuts/global/runProgramArgs",
|
||||
L"remapShortcuts/global/runProgramStartInDir",
|
||||
L"remapShortcuts/global/openUri",
|
||||
L"remapShortcuts/appSpecific/runProgramFilePath",
|
||||
L"remapShortcuts/appSpecific/runProgramArgs",
|
||||
L"remapShortcuts/appSpecific/runProgramStartInDir",
|
||||
L"remapShortcuts/appSpecific/openUri",
|
||||
} }, // avoid leaking personal information from text, URI or application mappings
|
||||
{ L"Workspaces/workspaces.json", { L"workspaces/applications/command-line-arguments" } },
|
||||
{ L"AdvancedPaste/settings.json", {
|
||||
L"properties/custom-actions/value/name",
|
||||
L"properties/custom-actions/value/prompt"
|
||||
} },
|
||||
};
|
||||
|
||||
vector<wstring> filesToDelete = {
|
||||
L"AdvancedPaste\\lastQuery.json",
|
||||
L"AdvancedPaste\\kernelQueryCache.json",
|
||||
L"PowerToys Run\\Cache",
|
||||
L"PowerRename\\replace-mru.json",
|
||||
L"PowerRename\\search-mru.json",
|
||||
L"PowerToys Run\\Settings\\UserSelectedRecord.json",
|
||||
L"PowerToys Run\\Settings\\QueryHistory.json",
|
||||
L"NewPlus\\Templates",
|
||||
L"etw",
|
||||
};
|
||||
|
||||
vector<wstring> GetXpathArray(wstring xpath)
|
||||
{
|
||||
vector<wstring> result;
|
||||
wstring cur = L"";
|
||||
for (auto ch : xpath)
|
||||
{
|
||||
if (ch == L'/')
|
||||
{
|
||||
result.push_back(cur);
|
||||
cur = L"";
|
||||
continue;
|
||||
}
|
||||
|
||||
cur += ch;
|
||||
}
|
||||
|
||||
if (!cur.empty())
|
||||
{
|
||||
result.push_back(cur);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void HideByXPath(IJsonValue& val, vector<wstring>& xpathArray, int p)
|
||||
{
|
||||
if (val.ValueType() == JsonValueType::Array)
|
||||
{
|
||||
for (auto it : val.GetArray())
|
||||
{
|
||||
HideByXPath(it, xpathArray, p);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (p == xpathArray.size() - 1)
|
||||
{
|
||||
if (val.ValueType() == JsonValueType::Object)
|
||||
{
|
||||
auto obj = val.GetObjectW();
|
||||
if (obj.HasKey(xpathArray[p]))
|
||||
{
|
||||
auto privateDatavalue = JsonValue::CreateStringValue(L"<private_data>");
|
||||
obj.SetNamedValue(xpathArray[p], privateDatavalue);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (val.ValueType() == JsonValueType::Object)
|
||||
{
|
||||
IJsonValue newVal;
|
||||
try
|
||||
{
|
||||
newVal = val.GetObjectW().GetNamedValue(xpathArray[p]);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HideByXPath(newVal, xpathArray, p + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void HideForFile(const path& dir, const wstring& relativePath)
|
||||
{
|
||||
path jsonPath = dir;
|
||||
jsonPath.append(relativePath);
|
||||
auto jObject = json::from_file(jsonPath.wstring());
|
||||
if (!jObject.has_value())
|
||||
{
|
||||
wprintf(L"Failed to parse file %s\n", jsonPath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
JsonValue jValue = json::value(jObject.value());
|
||||
for (auto xpath : escapeInfo[relativePath])
|
||||
{
|
||||
vector<wstring> xpathArray = GetXpathArray(xpath);
|
||||
HideByXPath(jValue, xpathArray, 0);
|
||||
}
|
||||
|
||||
json::to_file(jsonPath.wstring(), jObject.value());
|
||||
}
|
||||
|
||||
bool DeleteFolder(wstring path)
|
||||
{
|
||||
error_code err;
|
||||
remove_all(path, err);
|
||||
if (err.value() != 0)
|
||||
{
|
||||
wprintf_s(L"Failed to delete %s. Error code: %d\n", path.c_str(), err.value());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HideUserPrivateInfo(const filesystem::path& dir)
|
||||
{
|
||||
// Replace data in json files
|
||||
for (auto& it : escapeInfo)
|
||||
{
|
||||
HideForFile(dir, it.first);
|
||||
}
|
||||
|
||||
// Delete files
|
||||
for (auto it : filesToDelete)
|
||||
{
|
||||
auto path = dir;
|
||||
path = path.append(it);
|
||||
DeleteFolder(path);
|
||||
}
|
||||
}
|
||||
|
||||
void ReportWindowsVersion(const filesystem::path& tmpDir)
|
||||
{
|
||||
auto versionReportPath = tmpDir;
|
||||
versionReportPath = versionReportPath.append("windows-version.txt");
|
||||
OSVERSIONINFOEXW osInfo{};
|
||||
|
||||
try
|
||||
{
|
||||
NTSTATUS(WINAPI * RtlGetVersion)
|
||||
(LPOSVERSIONINFOEXW) = nullptr;
|
||||
*reinterpret_cast<FARPROC*>(& RtlGetVersion) = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
|
||||
if (RtlGetVersion)
|
||||
{
|
||||
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
|
||||
RtlGetVersion(&osInfo);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to get windows version info\n");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wofstream versionReport(versionReportPath);
|
||||
versionReport << "MajorVersion: " << osInfo.dwMajorVersion << endl;
|
||||
versionReport << "MinorVersion: " << osInfo.dwMinorVersion << endl;
|
||||
versionReport << "BuildNumber: " << osInfo.dwBuildNumber << endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to write to %s\n", versionReportPath.string().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ReportWindowsSettings(const filesystem::path& tmpDir)
|
||||
{
|
||||
std::wstring userLanguage;
|
||||
std::wstring userLocale;
|
||||
try
|
||||
{
|
||||
const auto lang = winrt::Windows::System::UserProfile::GlobalizationPreferences::Languages().GetAt(0);
|
||||
userLanguage = winrt::Windows::Globalization::Language{ lang }.DisplayName().c_str();
|
||||
wchar_t localeName[LOCALE_NAME_MAX_LENGTH]{};
|
||||
if (!LCIDToLocaleName(GetThreadLocale(), localeName, LOCALE_NAME_MAX_LENGTH, 0))
|
||||
{
|
||||
throw -1;
|
||||
}
|
||||
userLocale = localeName;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to get windows settings\n");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
wofstream settingsReport(tmpDir / "windows-settings.txt");
|
||||
settingsReport << "Preferred user language: " << userLanguage << endl;
|
||||
settingsReport << "User locale: " << userLocale << endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to write windows settings\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ReportDotNetInstallationInfo(const filesystem::path& tmpDir)
|
||||
{
|
||||
auto dotnetInfoPath = tmpDir;
|
||||
dotnetInfoPath.append("dotnet-installation-info.txt");
|
||||
try
|
||||
{
|
||||
wofstream dotnetReport(dotnetInfoPath);
|
||||
auto dotnetInfo = exec_and_read_output(LR"(dotnet --list-runtimes)");
|
||||
if (!dotnetInfo.has_value())
|
||||
{
|
||||
printf("Failed to get dotnet installation information\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dotnetReport << dotnetInfo.value().c_str();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to report dotnet installation information");
|
||||
}
|
||||
}
|
||||
|
||||
void ReportInstallerLogs(const filesystem::path& tmpDir, const filesystem::path& reportDir)
|
||||
{
|
||||
const char* bootstrapperLogFilePrefix = "powertoys-bootstrapper-msi-";
|
||||
const char* PTLogFilePrefix = "PowerToysMSIInstaller_";
|
||||
|
||||
for (auto& entry : directory_iterator{ tmpDir })
|
||||
{
|
||||
std::error_code ec;
|
||||
if (entry.is_directory(ec) || !entry.path().has_filename())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto fileName = entry.path().filename().string();
|
||||
if (!fileName.starts_with(bootstrapperLogFilePrefix) && !fileName.starts_with(PTLogFilePrefix))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
copy(entry.path(), reportDir / fileName, ec);
|
||||
}
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t* argv[], wchar_t*)
|
||||
{
|
||||
// Get path to save zip
|
||||
wstring saveZipPath;
|
||||
if (argc > 1)
|
||||
{
|
||||
saveZipPath = argv[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t buffer[MAX_PATH];
|
||||
if (SHGetSpecialFolderPath(HWND_DESKTOP, buffer, CSIDL_DESKTOP, FALSE))
|
||||
{
|
||||
saveZipPath = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Failed to retrieve the desktop path. Error code: %d\n", GetLastError());
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto settingsRootPath = PTSettingsHelper::get_root_save_folder_location();
|
||||
settingsRootPath += L"\\";
|
||||
|
||||
auto localLowPath = PTSettingsHelper::get_local_low_folder_location();
|
||||
localLowPath += L"\\logs\\";
|
||||
|
||||
const auto tempDir = temp_directory_path();
|
||||
auto reportDir = temp_directory_path() / "PowerToys\\";
|
||||
if (!DeleteFolder(reportDir))
|
||||
{
|
||||
printf("Failed to delete temp folder\n");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
copy(settingsRootPath, reportDir, copy_options::recursive);
|
||||
|
||||
// Remove updates folder contents
|
||||
DeleteFolder(reportDir / "Updates");
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to copy PowerToys folder\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
copy(localLowPath, reportDir, copy_options::recursive);
|
||||
}
|
||||
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to copy logs saved in LocalLow\n");
|
||||
}
|
||||
|
||||
#ifndef _DEBUG
|
||||
InstallationFolder::ReportStructure(reportDir);
|
||||
#endif
|
||||
|
||||
// Hide sensitive information
|
||||
HideUserPrivateInfo(reportDir);
|
||||
|
||||
// Write windows settings to the temporary folder
|
||||
ReportWindowsSettings(reportDir);
|
||||
|
||||
// Write monitors info to the temporary folder
|
||||
ReportMonitorInfo(reportDir);
|
||||
|
||||
// Write windows version info to the temporary folder
|
||||
ReportWindowsVersion(reportDir);
|
||||
|
||||
// Write dotnet installation info to the temporary folder
|
||||
ReportDotNetInstallationInfo(reportDir);
|
||||
|
||||
// Write registry to the temporary folder
|
||||
ReportRegistry(reportDir);
|
||||
|
||||
// Write gpo policies to the temporary folder
|
||||
ReportGPOValues(reportDir);
|
||||
|
||||
// Write compatibility tab info to the temporary folder
|
||||
ReportCompatibilityTab(reportDir);
|
||||
|
||||
// Write event viewer logs info to the temporary folder
|
||||
EventViewer::ReportEventViewerInfo(reportDir);
|
||||
|
||||
// Write AppXDeployment-Server event logs to the temporary folder
|
||||
EventViewer::ReportAppXDeploymentLogs(reportDir);
|
||||
|
||||
ReportInstallerLogs(tempDir, reportDir);
|
||||
|
||||
ReportInstalledContextMenuPackages(reportDir);
|
||||
|
||||
// Zip folder
|
||||
auto zipPath = path::path(saveZipPath);
|
||||
|
||||
try
|
||||
{
|
||||
ZipFolder(zipPath, reportDir);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to zip folder\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
DeleteFolder(reportDir);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "Package.h"
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
|
||||
std::optional<winrt::Windows::ApplicationModel::Package> GetPackage(std::wstring packageDisplayName)
|
||||
{
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Management::Deployment;
|
||||
|
||||
PackageManager packageManager;
|
||||
|
||||
for (auto const& package : packageManager.FindPackagesForUser({}))
|
||||
{
|
||||
const auto& packageFullName = std::wstring{ package.Id().FullName() };
|
||||
|
||||
if (packageFullName.contains(packageDisplayName))
|
||||
{
|
||||
return { package };
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::wstringstream GetPackageInfo(winrt::Windows::ApplicationModel::Package package) {
|
||||
std::wstringstream packageInfo;
|
||||
packageInfo << L"Display name: " << std::wstring(package.DisplayName()) << std::endl;
|
||||
packageInfo << L"Full name: " << std::wstring(package.Id().FullName()) << std::endl;
|
||||
packageInfo << L"Version: " << package.Id().Version().Major << L"."
|
||||
<< package.Id().Version().Minor << L"."
|
||||
<< package.Id().Version().Build << L"."
|
||||
<< package.Id().Version().Revision << L"." << std::endl;
|
||||
packageInfo << L"Publisher: " << std::wstring(package.Id().Publisher()) << std::endl;
|
||||
packageInfo << L"Status: " << (package.Status().VerifyIsOK() ? std::wstring(L"OK") : std::wstring(L"Not OK")) << std::endl;
|
||||
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
void ReportInstalledContextMenuPackages(const std::filesystem::path& reportDir)
|
||||
{
|
||||
const wchar_t* ImageResizerContextMenuPackageDisplayName = L"ImageResizerContextMenu";
|
||||
const wchar_t* PowerRenameContextMenuPackageDisplayName = L"PowerRenameContextMenu";
|
||||
|
||||
auto reportPath = reportDir;
|
||||
reportPath.append("context-menu-packages.txt");
|
||||
|
||||
std::wofstream packagesReport(reportPath);
|
||||
|
||||
try
|
||||
{
|
||||
auto imageResizerPackage = GetPackage(ImageResizerContextMenuPackageDisplayName);
|
||||
if (imageResizerPackage)
|
||||
{
|
||||
packagesReport << GetPackageInfo(*imageResizerPackage).str() << std::endl;
|
||||
}
|
||||
|
||||
auto powerRenamePackage = GetPackage(PowerRenameContextMenuPackageDisplayName);
|
||||
if (powerRenamePackage)
|
||||
{
|
||||
packagesReport << GetPackageInfo(*powerRenamePackage).str() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to report installed context menu packages");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
#include <winrt/Windows.ApplicationModel.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Management.Deployment.h>
|
||||
|
||||
std::optional<winrt::Windows::ApplicationModel::Package> GetPackage(std::wstring packageDisplayName);
|
||||
std::wstringstream GetPackageInfo(winrt::Windows::ApplicationModel::Package package);
|
||||
void ReportInstalledContextMenuPackages(const std::filesystem::path& reportDir);
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::vector<std::wstring> processes =
|
||||
{
|
||||
L"PowerToys.exe",
|
||||
L"PowerToys.Settings.exe",
|
||||
L"PowerToys.ColorPickerUI.exe",
|
||||
L"PowerToys.AdvancedPaste.exe",
|
||||
L"PowerToys.Awake.exe",
|
||||
L"PowerToys.FancyZonesEditor.exe",
|
||||
L"PowerToys.FancyZones.exe",
|
||||
L"PowerToys.FileLocksmithUI.exe",
|
||||
L"PowerToys.LightSwitch.exe",
|
||||
L"PowerToys.KeyboardManagerEngine.exe",
|
||||
L"PowerToys.KeyboardManagerEditor.exe",
|
||||
L"PowerToys.PowerAccent.exe",
|
||||
L"PowerToys.PowerLauncher.exe",
|
||||
L"PowerToys.PowerOCR.exe",
|
||||
L"PowerToys.MouseJumpUI.exe",
|
||||
L"PowerToys.MeasureToolUI.exe",
|
||||
L"PowerToys.ShortcutGuide.exe",
|
||||
L"PowerToys.PowerRename.exe",
|
||||
L"PowerToys.ImageResizer.exe",
|
||||
L"PowerToys.Update.exe",
|
||||
L"PowerToys.ActionRunner.exe",
|
||||
L"PowerToys.AlwaysOnTop.exe",
|
||||
L"PowerToys.Hosts.exe",
|
||||
L"PowerToys.GcodePreviewHandler.exe",
|
||||
L"PowerToys.GcodeThumbnailProvider.exe",
|
||||
L"PowerToys.BgcodePreviewHandler.exe",
|
||||
L"PowerToys.BgcodeThumbnailProvider.exe",
|
||||
L"PowerToys.MarkdownPreviewHandler.exe",
|
||||
L"PowerToys.MonacoPreviewHandler.exe",
|
||||
L"PowerToys.PdfPreviewHandler.exe",
|
||||
L"PowerToys.PdfThumbnailProvider.exe",
|
||||
L"PowerToys.QoiPreviewHandler.exe",
|
||||
L"PowerToys.QoiThumbnailProvider.exe",
|
||||
L"PowerToys.StlThumbnailProvider.exe",
|
||||
L"PowerToys.SvgPreviewHandler.exe",
|
||||
L"PowerToys.SvgThumbnailProvider.exe",
|
||||
L"PowerToys.RegistryPreview.exe",
|
||||
L"PowerToys.MouseWithoutBorders.exe",
|
||||
L"PowerToys.MouseWithoutBordersHelper.exe",
|
||||
L"PowerToys.MouseWithoutBordersService.exe",
|
||||
L"PowerToys.Peek.UI.exe",
|
||||
L"PowerToys.CropAndLock.exe",
|
||||
L"PowerToys.EnvironmentVariables.exe",
|
||||
L"PowerToys.WorkspacesSnapshotTool.exe",
|
||||
L"PowerToys.WorkspacesLauncher.exe",
|
||||
L"PowerToys.WorkspacesLauncherUI.exe",
|
||||
L"PowerToys.WorkspacesWindowArranger.exe",
|
||||
L"PowerToys.WorkspacesEditor.exe",
|
||||
L"PowerToys.ZoomIt.exe",
|
||||
L"Microsoft.CmdPal.UI.exe",
|
||||
};
|
||||
@@ -0,0 +1,318 @@
|
||||
#include "RegistryUtils.h"
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
extern std::vector<std::wstring> processes;
|
||||
|
||||
namespace
|
||||
{
|
||||
vector<pair<HKEY, wstring>> registryKeys = {
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{DD5CACDA-7C2E-4997-A62A-04A597B58F76}" },
|
||||
{ HKEY_CLASSES_ROOT, L"powertoys" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{ddee2b8a-6807-48a6-bb20-2338174ff779}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{36B27788-A8BB-4698-A756-DF9F11F64F84}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{45769bcc-e8fd-42d0-947e-02beef77a1f5}" },
|
||||
{ HKEY_CLASSES_ROOT, L"AppID\\{CF142243-F059-45AF-8842-DBBE9783DB14}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{07665729-6243-4746-95b7-79579308d1b2}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{ec52dea8-7c9f-4130-a77b-1737d0418507}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{dd8de316-7b01-48e7-ba21-e92c646704af}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{8AA07897-C30B-4543-865B-00A0E5A1B32D}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{BCC13D15-9720-4CC4-8371-EA74A274741E}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{BFEE99B4-B74D-4348-BCA5-E757029647FF}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{c28761a0-8420-43ad-bff3-40400543e2d4}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{8BC8AFC2-4E7C-4695-818E-8C1FFDCEA2AF}" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{51B4D7E5-7568-4234-B4BB-47FB3C016A69}\\InprocServer32" },
|
||||
{ HKEY_CLASSES_ROOT, L"CLSID\\{0440049F-D1DC-4E46-B27B-98393D79486B}" },
|
||||
{ HKEY_CLASSES_ROOT, L"AllFileSystemObjects\\ShellEx\\ContextMenuHandlers\\PowerRenameExt" },
|
||||
{ HKEY_CLASSES_ROOT, L".svg\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".svg\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
|
||||
{ HKEY_CLASSES_ROOT, L".md\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".pdf\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".pdf\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
|
||||
{ HKEY_CLASSES_ROOT, L".qoi\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".qoi\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
|
||||
{ HKEY_CLASSES_ROOT, L".gcode\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".gcode\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
|
||||
{ HKEY_CLASSES_ROOT, L".bgcode\\shellex\\{8895b1c6-b41f-4c1c-a562-0d564250836f}" },
|
||||
{ HKEY_CLASSES_ROOT, L".bgcode\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" },
|
||||
{ HKEY_CLASSES_ROOT, L".stl\\shellex\\{E357FCCD-A995-4576-B01F-234630154E96}" }
|
||||
};
|
||||
|
||||
vector<tuple<HKEY, wstring, wstring>> registryValues = {
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{ddee2b8a-6807-48a6-bb20-2338174ff779}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{45769bcc-e8fd-42d0-947e-02beef77a1f5}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{07665729-6243-4746-95b7-79579308d1b2}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{ec52dea8-7c9f-4130-a77b-1737d0418507}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{dd8de316-7b01-48e7-ba21-e92c646704af}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\PreviewHandlers", L"{8AA07897-C30B-4543-865B-00A0E5A1B32D}" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", L"prevhost.exe" },
|
||||
{ HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION", L"dllhost.exe" }
|
||||
};
|
||||
|
||||
// Is there a Windows API for this?
|
||||
std::unordered_map<HKEY, wstring> hKeyToString = {
|
||||
{ HKEY_CLASSES_ROOT, L"HKEY_CLASSES_ROOT" },
|
||||
{ HKEY_CURRENT_USER, L"HKEY_CURRENT_USER" },
|
||||
{ HKEY_LOCAL_MACHINE, L"HKEY_LOCAL_MACHINE" },
|
||||
{ HKEY_PERFORMANCE_DATA, L"HKEY_PERFORMANCE_DATA" },
|
||||
{ HKEY_PERFORMANCE_NLSTEXT, L"HKEY_PERFORMANCE_NLSTEXT"},
|
||||
{ HKEY_PERFORMANCE_TEXT, L"HKEY_PERFORMANCE_TEXT"},
|
||||
{ HKEY_USERS, L"HKEY_USERS"},
|
||||
};
|
||||
|
||||
vector<pair<wstring, wstring>> QueryValues(HKEY key)
|
||||
{
|
||||
DWORD cValues;
|
||||
RegQueryInfoKeyW(key, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &cValues, nullptr, nullptr, nullptr, nullptr);
|
||||
TCHAR achValue[255];
|
||||
DWORD cchValue = 255;
|
||||
LPBYTE value;
|
||||
vector<pair<wstring, wstring>> results;
|
||||
// Values
|
||||
if (cValues)
|
||||
{
|
||||
for (DWORD i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
|
||||
{
|
||||
cchValue = 255;
|
||||
achValue[0] = '\0';
|
||||
value = new BYTE[16383];
|
||||
retCode = RegEnumValueW(key, i, achValue, &cchValue, NULL, NULL, value, &cchValue);
|
||||
|
||||
if (retCode == ERROR_SUCCESS)
|
||||
{
|
||||
results.push_back({ achValue, (LPCTSTR)value });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void QueryKey(HKEY key, wostream& stream, int indent = 1)
|
||||
{
|
||||
TCHAR achKey[255];
|
||||
DWORD cbName;
|
||||
TCHAR achClass[MAX_PATH] = TEXT("");
|
||||
DWORD cchClassName = MAX_PATH;
|
||||
DWORD cSubKeys = 0;
|
||||
DWORD cbMaxSubKey;
|
||||
DWORD cchMaxClass;
|
||||
DWORD cValues;
|
||||
DWORD cchMaxValue;
|
||||
DWORD cbMaxValueData;
|
||||
|
||||
DWORD i, retCode;
|
||||
|
||||
TCHAR achValue[255];
|
||||
DWORD cchValue = 255;
|
||||
LPBYTE value;
|
||||
|
||||
// Get the class name and the value count.
|
||||
retCode = RegQueryInfoKeyW(key, achClass, &cchClassName, NULL, &cSubKeys, &cbMaxSubKey, &cchMaxClass, &cValues, &cchMaxValue, &cbMaxValueData, NULL, NULL);
|
||||
|
||||
// Values
|
||||
if (cValues)
|
||||
{
|
||||
for (i = 0, retCode = ERROR_SUCCESS; i < cValues; i++)
|
||||
{
|
||||
cchValue = 255;
|
||||
achValue[0] = '\0';
|
||||
value = new BYTE[16383];
|
||||
retCode = RegEnumValueW(key, i, achValue, &cchValue, NULL, NULL, value, &cchValue);
|
||||
|
||||
if (retCode == ERROR_SUCCESS)
|
||||
{
|
||||
stream << wstring(indent, '\t');
|
||||
if (achValue[0] == '\0')
|
||||
{
|
||||
stream << "Default";
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << achValue;
|
||||
}
|
||||
|
||||
stream << " > " << reinterpret_cast<LPCTSTR>(value) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "Error " << retCode << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keys
|
||||
if (cSubKeys)
|
||||
{
|
||||
std::vector<wstring> vecKeys;
|
||||
vecKeys.reserve(cSubKeys);
|
||||
|
||||
for (i = 0; i < cSubKeys; ++i)
|
||||
{
|
||||
cbName = 255;
|
||||
retCode = RegEnumKeyExW(key, i, achKey, &cbName, NULL, NULL, NULL, NULL);
|
||||
if (retCode == ERROR_SUCCESS)
|
||||
{
|
||||
vecKeys.push_back(achKey);
|
||||
}
|
||||
}
|
||||
|
||||
// Parsing subkeys recursively
|
||||
for (auto& child : vecKeys)
|
||||
{
|
||||
HKEY hTestKey;
|
||||
if (RegOpenKeyExW(key, child.c_str(), 0, KEY_READ, &hTestKey) == ERROR_SUCCESS)
|
||||
{
|
||||
stream << wstring(indent, '\t') << child << "\n";
|
||||
QueryKey(hTestKey, stream, indent + 1);
|
||||
RegCloseKey(hTestKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << "Error " << retCode << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReportCompatibilityTab(HKEY key, wofstream& report)
|
||||
{
|
||||
map<wstring, wstring> flags;
|
||||
for (auto app : processes)
|
||||
{
|
||||
flags[app] = L"";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
HKEY outKey;
|
||||
LONG result = RegOpenKeyExW(key, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, KEY_READ, &outKey);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
auto values = QueryValues(outKey);
|
||||
for (auto value : values)
|
||||
{
|
||||
for (auto app : processes)
|
||||
{
|
||||
if (value.first.find(app) != wstring::npos)
|
||||
{
|
||||
flags[app] += value.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
report << "Failed to get the report. " << get_last_error_or_default(GetLastError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
report << "Failed to get the report";
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto flag : flags)
|
||||
{
|
||||
report << flag.first << ": " << flag.second << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void ReportCompatibilityTab(const std::filesystem::path& tmpDir)
|
||||
{
|
||||
auto reportPath = tmpDir;
|
||||
reportPath.append(L"compatibility-tab-info.txt");
|
||||
wofstream report(reportPath);
|
||||
report << "Current user report" << endl;
|
||||
ReportCompatibilityTab(HKEY_CURRENT_USER, report);
|
||||
report << endl << endl;
|
||||
report << "Local machine report" << endl;
|
||||
ReportCompatibilityTab(HKEY_LOCAL_MACHINE, report);
|
||||
}
|
||||
|
||||
void ReportRegistry(const filesystem::path& tmpDir)
|
||||
{
|
||||
auto registryReportPath = tmpDir;
|
||||
registryReportPath.append("registry-report-info.txt");
|
||||
|
||||
wofstream registryReport(registryReportPath);
|
||||
try
|
||||
{
|
||||
for (auto [rootKey, subKey] : registryKeys)
|
||||
{
|
||||
registryReport << hKeyToString[rootKey] << "\\" << subKey << "\n";
|
||||
|
||||
HKEY outKey;
|
||||
LONG result = RegOpenKeyExW(rootKey, subKey.c_str(), 0, KEY_READ, &outKey);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
QueryKey(outKey, registryReport);
|
||||
RegCloseKey(rootKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
registryReport << "ERROR " << result << "\n";
|
||||
}
|
||||
|
||||
registryReport << "\n";
|
||||
}
|
||||
|
||||
for (auto [rootKey, subKey, value] : registryValues)
|
||||
{
|
||||
registryReport << hKeyToString[rootKey] << "\\" << subKey << "\n";
|
||||
|
||||
// Reading size
|
||||
DWORD dataSize = 0;
|
||||
DWORD flags = RRF_RT_ANY;
|
||||
DWORD type;
|
||||
LONG result = RegGetValueW(rootKey, subKey.c_str(), value.c_str(), flags, &type, NULL, &dataSize);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
// Reading value
|
||||
if (type == REG_SZ) // string
|
||||
{
|
||||
std::wstring data(dataSize / sizeof(wchar_t) + 1, L' ');
|
||||
result = RegGetValueW(rootKey, subKey.c_str(), value.c_str(), flags, &type, &data[0], &dataSize);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
registryReport << "\t" << value << " > " << data << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
registryReport << "ERROR " << result << "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD data = 0;
|
||||
dataSize = sizeof(data);
|
||||
result = RegGetValueW(rootKey, subKey.c_str(), value.c_str(), flags, &type, &data, &dataSize);
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
registryReport << "\t" << value << " > " << data << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
registryReport << "ERROR " << result << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(rootKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
registryReport << "ERROR " << result << "\n";
|
||||
}
|
||||
|
||||
registryReport << "\n";
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to get registry keys\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <unordered_map>
|
||||
#include <Windows.h>
|
||||
|
||||
void ReportRegistry(const std::filesystem::path& tmpDir);
|
||||
void ReportCompatibilityTab(const std::filesystem::path& tmpDir);
|
||||
@@ -0,0 +1,111 @@
|
||||
#include "ReportGPOValues.h"
|
||||
#include <common/utils/gpo.h>
|
||||
#include <fstream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
std::wstring gpo_rule_configured_to_string(powertoys_gpo::gpo_rule_configured_t gpo_rule)
|
||||
{
|
||||
switch (gpo_rule)
|
||||
{
|
||||
case powertoys_gpo::gpo_rule_configured_wrong_value:
|
||||
return L"wrong_value";
|
||||
case powertoys_gpo::gpo_rule_configured_unavailable:
|
||||
return L"can't_access";
|
||||
case powertoys_gpo::gpo_rule_configured_not_configured:
|
||||
return L"not_configured";
|
||||
case powertoys_gpo::gpo_rule_configured_disabled:
|
||||
return L"disabled";
|
||||
case powertoys_gpo::gpo_rule_configured_enabled:
|
||||
return L"enabled";
|
||||
default:
|
||||
return L"Unrecognized gpo_rule_configured_t value.";
|
||||
}
|
||||
}
|
||||
|
||||
std::wstring gpo_string_to_string(const std::wstring &gpo_value)
|
||||
{
|
||||
if (gpo_value == L"")
|
||||
{
|
||||
return L"not_configured";
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::regex_replace(gpo_value, std::wregex(L"\r\n"), std::wstring(L"|"));
|
||||
}
|
||||
}
|
||||
|
||||
void ReportGPOValues(const std::filesystem::path &tmpDir)
|
||||
{
|
||||
auto reportPath = tmpDir;
|
||||
reportPath.append(L"gpo-configuration-info.txt");
|
||||
std::wofstream report(reportPath);
|
||||
report << "GPO policies configuration" << std::endl;
|
||||
report << "getConfiguredAdvancedPasteEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredAdvancedPasteEnabledValue()) << std::endl;
|
||||
report << "getConfiguredAlwaysOnTopEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredAlwaysOnTopEnabledValue()) << std::endl;
|
||||
report << "getConfiguredAwakeEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredAwakeEnabledValue()) << std::endl;
|
||||
report << "getConfiguredCmdPalEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredCmdPalEnabledValue()) << std::endl;
|
||||
report << "getConfiguredColorPickerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredColorPickerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredCropAndLockEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredCropAndLockEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFancyZonesEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFancyZonesEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFileLocksmithEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFileLocksmithEnabledValue()) << std::endl;
|
||||
report << "getConfiguredLightSwitchEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredLightSwitchEnabledValue()) << std::endl;
|
||||
report << "getConfiguredGrabAndMoveEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredGrabAndMoveEnabledValue()) << std::endl;
|
||||
report << "getConfiguredSvgPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredSvgPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMarkdownPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMarkdownPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMonacoPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMonacoPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPdfPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPdfPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredGcodePreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredGcodePreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredBgcodePreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredBgcodePreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredSvgThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredSvgThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPdfThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPdfThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredGcodeThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredGcodeThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredBgcodeThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredBgcodeThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredStlThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredStlThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredHostsFileEditorEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredHostsFileEditorEnabledValue()) << std::endl;
|
||||
report << "getConfiguredImageResizerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredImageResizerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredKeyboardManagerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredKeyboardManagerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredFindMyMouseEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredFindMyMouseEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMouseHighlighterEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMouseHighlighterEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMouseJumpEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMouseJumpEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMousePointerCrosshairsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMousePointerCrosshairsEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMouseWithoutBordersEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMouseWithoutBordersEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPowerRenameEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPowerRenameEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPowerLauncherEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPowerLauncherEnabledValue()) << std::endl;
|
||||
report << "getConfiguredWorkspacesEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredWorkspacesEnabledValue()) << std::endl;
|
||||
report << "getConfiguredQuickAccentEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredQuickAccentEnabledValue()) << std::endl;
|
||||
report << "getConfiguredScreenRulerEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredScreenRulerEnabledValue()) << std::endl;
|
||||
report << "getConfiguredShortcutGuideEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredShortcutGuideEnabledValue()) << std::endl;
|
||||
report << "getConfiguredTextExtractorEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredTextExtractorEnabledValue()) << std::endl;
|
||||
report << "getConfiguredPeekEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredPeekEnabledValue()) << std::endl;
|
||||
report << "getConfiguredZoomItEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredZoomItEnabledValue()) << std::endl;
|
||||
report << "getDisableAutomaticUpdateDownloadValue: " << gpo_rule_configured_to_string(powertoys_gpo::getDisableAutomaticUpdateDownloadValue()) << std::endl;
|
||||
report << "getSuspendNewUpdateToastValue: " << gpo_rule_configured_to_string(powertoys_gpo::getSuspendNewUpdateToastValue()) << std::endl;
|
||||
report << "getDisableNewUpdateToastValue: " << gpo_rule_configured_to_string(powertoys_gpo::getDisableNewUpdateToastValue()) << std::endl;
|
||||
report << "getDisableShowWhatsNewAfterUpdatesValue: " << gpo_rule_configured_to_string(powertoys_gpo::getDisableShowWhatsNewAfterUpdatesValue()) << std::endl;
|
||||
report << "getAllowExperimentationValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowExperimentationValue()) << std::endl;
|
||||
report << "getConfiguredQoiPreviewEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredQoiPreviewEnabledValue()) << std::endl;
|
||||
report << "getConfiguredQoiThumbnailsEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredQoiThumbnailsEnabledValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteOnlineAIModelsValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteOnlineAIModelsValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteOpenAIValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteOpenAIValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteAzureOpenAIValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteAzureOpenAIValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteAzureAIInferenceValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteAzureAIInferenceValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteMistralValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteMistralValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteGoogleValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteGoogleValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteOllamaValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteOllamaValue()) << std::endl;
|
||||
report << "getAllowedAdvancedPasteFoundryLocalValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowedAdvancedPasteFoundryLocalValue()) << std::endl;
|
||||
report << "getConfiguredMwbClipboardSharingEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbClipboardSharingEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMwbFileTransferEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbFileTransferEnabledValue()) << std::endl;
|
||||
report << "getConfiguredMwbUseOriginalUserInterfaceValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbUseOriginalUserInterfaceValue()) << std::endl;
|
||||
report << "getConfiguredMwbDisallowBlockingScreensaverValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbDisallowBlockingScreensaverValue()) << std::endl;
|
||||
report << "getConfiguredMwbAllowServiceModeValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbAllowServiceModeValue()) << std::endl;
|
||||
report << "getConfiguredMwbSameSubnetOnlyValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbSameSubnetOnlyValue()) << std::endl;
|
||||
report << "getConfiguredMwbValidateRemoteIpValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbValidateRemoteIpValue()) << std::endl;
|
||||
report << "getConfiguredMwbDisableUserDefinedIpMappingRulesValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredMwbDisableUserDefinedIpMappingRulesValue()) << std::endl;
|
||||
report << "getConfiguredMwbPolicyDefinedIpMappingRules: " << gpo_string_to_string(powertoys_gpo::getConfiguredMwbPolicyDefinedIpMappingRules()) << std::endl;
|
||||
report << "getConfiguredNewPlusEnabledValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredNewPlusEnabledValue()) << std::endl;
|
||||
report << "getConfiguredNewPlusHideTemplateFilenameExtensionValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredNewPlusHideTemplateFilenameExtensionValue()) << std::endl;
|
||||
report << "getAllowDataDiagnosticsValue: " << gpo_rule_configured_to_string(powertoys_gpo::getAllowDataDiagnosticsValue()) << std::endl;
|
||||
report << "getConfiguredRunAtStartupValue: " << gpo_rule_configured_to_string(powertoys_gpo::getConfiguredRunAtStartupValue()) << std::endl;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
void ReportGPOValues(const std::filesystem::path& tmpDir);
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include "ReportMonitorInfo.h"
|
||||
#include <Windows.h>
|
||||
#include <filesystem>
|
||||
#include "../../../src/common/utils/winapi_error.h"
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
int BuildMonitorInfoReport(std::wostream& os)
|
||||
{
|
||||
struct capture
|
||||
{
|
||||
std::wostream* os = nullptr;
|
||||
};
|
||||
|
||||
auto callback = [](HMONITOR monitor, HDC, RECT*, LPARAM prm) -> BOOL {
|
||||
std::wostream& os = *(reinterpret_cast<capture*>(prm))->os;
|
||||
MONITORINFOEX mi;
|
||||
mi.cbSize = sizeof(mi);
|
||||
|
||||
if (GetMonitorInfoW(monitor, &mi))
|
||||
{
|
||||
os << "GetMonitorInfo OK\n";
|
||||
DISPLAY_DEVICE displayDevice = { sizeof(displayDevice) };
|
||||
|
||||
DWORD i = 0;
|
||||
while (EnumDisplayDevicesW(mi.szDevice, i++, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
|
||||
{
|
||||
const bool active = displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE;
|
||||
const bool mirroring = displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER;
|
||||
os << "EnumDisplayDevices OK:\n"
|
||||
<< "\tMirroring = " << mirroring << '\n'
|
||||
<< "\tActive = " << active << '\n'
|
||||
<< "\tDeviceID = " << displayDevice.DeviceID << '\n'
|
||||
<< "\tDeviceKey = " << displayDevice.DeviceKey << '\n'
|
||||
<< "\tDeviceName = " << displayDevice.DeviceName << '\n'
|
||||
<< "\tDeviceString = " << displayDevice.DeviceString << '\n';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto message = get_last_error_message(GetLastError());
|
||||
os << "GetMonitorInfo FAILED: " << (message.has_value() ? message.value() : L"") << '\n';
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
capture c;
|
||||
c.os = &os;
|
||||
if (EnumDisplayMonitors(nullptr, nullptr, callback, reinterpret_cast<LPARAM>(& c)))
|
||||
{
|
||||
os << "EnumDisplayMonitors OK\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
auto message = get_last_error_message(GetLastError());
|
||||
os << "EnumDisplayMonitors FAILED: " << (message.has_value() ? message.value() : L"") << '\n';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ReportMonitorInfo(const filesystem::path& tmpDir)
|
||||
{
|
||||
auto monitorReportPath = tmpDir;
|
||||
monitorReportPath.append("monitor-report-info.txt");
|
||||
|
||||
try
|
||||
{
|
||||
wofstream monitorReport(monitorReportPath);
|
||||
monitorReport << "GetSystemMetrics = " << GetSystemMetrics(SM_CMONITORS) << '\n';
|
||||
BuildMonitorInfoReport(monitorReport);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
printf("Failed to report monitor info. %s\n", ex.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
printf("Failed to report monitor info\n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <fstream>
|
||||
|
||||
void ReportMonitorInfo(const std::filesystem::path& tmpDir);
|
||||
@@ -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">";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include <winrt/Windows.Data.Xml.Dom.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "ZipFolder.h"
|
||||
#include <common/utils/timeutil.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
|
||||
#include <format>
|
||||
#include <wil/stl.h>
|
||||
#include <wil/win32_helpers.h>
|
||||
|
||||
void ZipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath)
|
||||
{
|
||||
const auto reportFilename{
|
||||
std::format("PowerToysReport_{0}.zip",
|
||||
timeutil::format_as_local("%F-%H-%M-%S", timeutil::now()))
|
||||
};
|
||||
const auto finalReportFullPath{ zipPath / reportFilename };
|
||||
|
||||
const auto tempReportFilename{ reportFilename + ".tmp" };
|
||||
const auto tempReportFullPath{ zipPath / tempReportFilename };
|
||||
|
||||
// tar -c --format=zip -f "ReportFile.zip" *
|
||||
const auto executable{ wil::ExpandEnvironmentStringsW<std::wstring>(LR"(%WINDIR%\System32\tar.exe)") };
|
||||
auto commandline{ std::format(LR"("{0}" -c --format=zip -f "{1}" *)", executable, tempReportFullPath.wstring()) };
|
||||
|
||||
const auto folderPathAsString{ folderPath.lexically_normal().wstring() };
|
||||
|
||||
wil::unique_process_information pi;
|
||||
STARTUPINFOW si{ .cb = sizeof(STARTUPINFOW) };
|
||||
if (!CreateProcessW(executable.c_str(),
|
||||
commandline.data() /* must be mutable */,
|
||||
nullptr,
|
||||
nullptr,
|
||||
FALSE,
|
||||
DETACHED_PROCESS,
|
||||
nullptr,
|
||||
folderPathAsString.c_str(),
|
||||
&si,
|
||||
&pi))
|
||||
{
|
||||
printf("Cannot open zip.");
|
||||
throw -1;
|
||||
}
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
|
||||
std::error_code err{};
|
||||
std::filesystem::rename(tempReportFullPath, finalReportFullPath, err);
|
||||
if (err.value() != 0)
|
||||
{
|
||||
wprintf_s(L"Failed to rename %s. Error code: %d\n", tempReportFullPath.native().c_str(), err.value());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <filesystem>
|
||||
|
||||
void ZipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath);
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.250303.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.260126.7" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by BugReportTool.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys BugReport Tool"
|
||||
#define INTERNAL_NAME "PowerToys.BugReportTool"
|
||||
#define ORIGINAL_FILENAME "PowerToys.BugReportTool.exe"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
Reference in New Issue
Block a user