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

This commit is contained in:
wehub-resource-sync
2026-07-13 12:16:02 +08:00
commit 79031da543
8235 changed files with 1365916 additions and 0 deletions
+41
View File
@@ -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)&lt;%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)&lt;%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);
};
+406
View File
@@ -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
//////////////////////////////