diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index cf5b2ac09a..c10f9b5ce8 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -2231,6 +2231,7 @@ workaround workflow workspaces wostream +wostringstream wox wparam wpf diff --git a/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj b/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj index 7446321e05..562580b463 100644 --- a/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj +++ b/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj @@ -38,8 +38,8 @@ - - + + @@ -54,8 +54,8 @@ - - + + diff --git a/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj.filters b/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj.filters index 1873491280..920c9eff95 100644 --- a/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj.filters +++ b/tools/BugReportTool/BugReportTool/BugReportTool.vcxproj.filters @@ -5,12 +5,12 @@ - + ZipTools - + @@ -18,13 +18,13 @@ - + ZipTools - + \ No newline at end of file diff --git a/tools/BugReportTool/BugReportTool/Main.cpp b/tools/BugReportTool/BugReportTool/Main.cpp index e57cf19193..5b45fd68c1 100644 --- a/tools/BugReportTool/BugReportTool/Main.cpp +++ b/tools/BugReportTool/BugReportTool/Main.cpp @@ -15,7 +15,7 @@ #include #include "ReportMonitorInfo.h" -#include "ReportRegistry.h" +#include "RegistryUtils.h" using namespace std; using namespace std::filesystem; using namespace winrt::Windows::Data::Json; @@ -33,7 +33,7 @@ vector filesToDelete = { L"PowerToys Run\\Settings\\QueryHistory.json" }; -vector getXpathArray(wstring xpath) +vector GetXpathArray(wstring xpath) { vector result; wstring cur = L""; @@ -57,13 +57,13 @@ vector getXpathArray(wstring xpath) return result; } -void hideByXPath(IJsonValue& val, vector& xpathArray, int p) +void HideByXPath(IJsonValue& val, vector& xpathArray, int p) { if (val.ValueType() == JsonValueType::Array) { for (auto it : val.GetArray()) { - hideByXPath(it, xpathArray, p); + HideByXPath(it, xpathArray, p); } return; @@ -96,11 +96,11 @@ void hideByXPath(IJsonValue& val, vector& xpathArray, int p) return; } - hideByXPath(newVal, xpathArray, p + 1); + HideByXPath(newVal, xpathArray, p + 1); } } -void hideForFile(const path& dir, const wstring& relativePath) +void HideForFile(const path& dir, const wstring& relativePath) { path jsonPath = dir; jsonPath.append(relativePath); @@ -114,14 +114,14 @@ void hideForFile(const path& dir, const wstring& relativePath) JsonValue jValue = json::value(jObject.value()); for (auto xpath : escapeInfo[relativePath]) { - vector xpathArray = getXpathArray(xpath); - hideByXPath(jValue, xpathArray, 0); + vector xpathArray = GetXpathArray(xpath); + HideByXPath(jValue, xpathArray, 0); } json::to_file(jsonPath.wstring(), jObject.value()); } -bool deleteFolder(wstring path) +bool DeleteFolder(wstring path) { error_code err; remove_all(path, err); @@ -134,12 +134,12 @@ bool deleteFolder(wstring path) return true; } -void hideUserPrivateInfo(const filesystem::path& dir) +void HideUserPrivateInfo(const filesystem::path& dir) { // Replace data in json files for (auto& it : escapeInfo) { - hideForFile(dir, it.first); + HideForFile(dir, it.first); } // delete files @@ -147,11 +147,11 @@ void hideUserPrivateInfo(const filesystem::path& dir) { auto path = dir; path = path.append(it); - deleteFolder(path); + DeleteFolder(path); } } -void reportWindowsVersion(const filesystem::path& tmpDir) +void ReportWindowsVersion(const filesystem::path& tmpDir) { auto versionReportPath = tmpDir; versionReportPath = versionReportPath.append("windows-version.txt"); @@ -187,7 +187,7 @@ void reportWindowsVersion(const filesystem::path& tmpDir) } } -void reportWindowsSettings(const filesystem::path& tmpDir) +void ReportWindowsSettings(const filesystem::path& tmpDir) { std::wstring userLanguage; std::wstring userLocale; @@ -221,7 +221,7 @@ void reportWindowsSettings(const filesystem::path& tmpDir) } -void reportDotNetInstallationInfo(const filesystem::path& tmpDir) +void ReportDotNetInstallationInfo(const filesystem::path& tmpDir) { auto dotnetInfoPath = tmpDir; dotnetInfoPath.append("dotnet-installation-info.txt"); @@ -271,7 +271,7 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) // Copy to a temp folder auto tmpDir = temp_directory_path(); tmpDir = tmpDir.append("PowerToys\\"); - if (!deleteFolder(tmpDir)) + if (!DeleteFolder(tmpDir)) { printf("Failed to delete temp folder\n"); return 1; @@ -281,7 +281,7 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) { copy(settingsRootPath, tmpDir, copy_options::recursive); // Remove updates folder contents - deleteFolder(tmpDir / "Updates"); + DeleteFolder(tmpDir / "Updates"); } catch (...) { @@ -290,22 +290,25 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) } // Hide sensitive information - hideUserPrivateInfo(tmpDir); + HideUserPrivateInfo(tmpDir); // Write windows settings to the temporary folder - reportWindowsSettings(tmpDir); + ReportWindowsSettings(tmpDir); // Write monitors info to the temporary folder reportMonitorInfo(tmpDir); // Write windows version info to the temporary folder - reportWindowsVersion(tmpDir); + ReportWindowsVersion(tmpDir); // Write dotnet installation info to the temporary folder - reportDotNetInstallationInfo(tmpDir); + ReportDotNetInstallationInfo(tmpDir); // Write registry to the temporary folder - reportRegistry(tmpDir); + ReportRegistry(tmpDir); + + // Write compatibility tab info to the temporary folder + ReportCompatibilityTab(tmpDir); // Zip folder auto zipPath = path::path(saveZipPath); @@ -316,7 +319,7 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) try { - zipFolder(zipPath, tmpDir); + ZipFolder(zipPath, tmpDir); } catch (...) { @@ -324,6 +327,6 @@ int wmain(int argc, wchar_t* argv[], wchar_t*) return 1; } - deleteFolder(tmpDir); + DeleteFolder(tmpDir); return 0; } diff --git a/tools/BugReportTool/BugReportTool/ReportRegistry.cpp b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp similarity index 70% rename from tools/BugReportTool/BugReportTool/ReportRegistry.cpp rename to tools/BugReportTool/BugReportTool/RegistryUtils.cpp index 5d19cc5128..e788000950 100644 --- a/tools/BugReportTool/BugReportTool/ReportRegistry.cpp +++ b/tools/BugReportTool/BugReportTool/RegistryUtils.cpp @@ -1,4 +1,6 @@ -#include "ReportRegistry.h" +#include "RegistryUtils.h" +#include +#include using namespace std; @@ -38,7 +40,35 @@ namespace { HKEY_USERS, L"HKEY_USERS"}, }; - void queryKey(HKEY key, wofstream& stream, int indent = 1) + vector> QueryValues(HKEY key) + { + DWORD cValues; + DWORD retCode = RegQueryInfoKeyW(key, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &cValues, nullptr, nullptr, nullptr, nullptr); + TCHAR achValue[255]; + DWORD cchValue = 255; + LPBYTE value; + vector> 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; @@ -114,7 +144,7 @@ namespace if (RegOpenKeyExW(key, child.c_str(), 0, KEY_READ, &hTestKey) == ERROR_SUCCESS) { stream << wstring(indent, '\t') << child << "\n"; - queryKey(hTestKey, stream, indent + 1); + QueryKey(hTestKey, stream, indent + 1); RegCloseKey(hTestKey); } else @@ -126,7 +156,74 @@ namespace } } -void reportRegistry(const filesystem::path& tmpDir) +void ReportCompatibilityTab(HKEY key, wofstream& report) +{ + vector apps + { + L"PowerToys.exe", + L"ColorPickerUI.exe", + L"FancyZonesEditor.exe", + L"PowerToys.KeyboardManagerEditor.exe", + L"PowerToys.KeyboardManagerEditor.exe", + L"PowerLauncher.exe", + L"PowerToys.ShortcutGuide.exe" + }; + + map flags; + for (auto app : apps) + { + 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 : apps) + { + 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"); @@ -142,7 +239,7 @@ void reportRegistry(const filesystem::path& tmpDir) LONG result = RegOpenKeyExW(rootKey, subKey.c_str(), 0, KEY_READ, &outKey); if (result == ERROR_SUCCESS) { - queryKey(outKey, registryReport); + QueryKey(outKey, registryReport); RegCloseKey(rootKey); } else diff --git a/tools/BugReportTool/BugReportTool/ReportRegistry.h b/tools/BugReportTool/BugReportTool/RegistryUtils.h similarity index 52% rename from tools/BugReportTool/BugReportTool/ReportRegistry.h rename to tools/BugReportTool/BugReportTool/RegistryUtils.h index 01cd964a3e..dd2d20c6b2 100644 --- a/tools/BugReportTool/BugReportTool/ReportRegistry.h +++ b/tools/BugReportTool/BugReportTool/RegistryUtils.h @@ -7,4 +7,5 @@ #include #include -void reportRegistry(const std::filesystem::path& tmpDir); +void ReportRegistry(const std::filesystem::path& tmpDir); +void ReportCompatibilityTab(const std::filesystem::path& tmpDir); \ No newline at end of file diff --git a/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.cpp b/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.cpp index 6220fcbdd1..4d5c781c27 100644 --- a/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.cpp +++ b/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.cpp @@ -1,7 +1,7 @@ -#include "zipfolder.h" +#include "ZipFolder.h" #include "..\..\..\..\deps\cziplib\src\zip.h" -void zipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath) +void ZipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath) { struct zip_t* zip = zip_open(zipPath.string().c_str(), ZIP_DEFAULT_COMPRESSION_LEVEL, 'w'); if (!zip) diff --git a/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.h b/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.h index 04f9e7c682..e4667aceaf 100644 --- a/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.h +++ b/tools/BugReportTool/BugReportTool/ZipTools/zipfolder.h @@ -1,4 +1,4 @@ #pragma once #include -void zipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath); \ No newline at end of file +void ZipFolder(std::filesystem::path zipPath, std::filesystem::path folderPath); \ No newline at end of file