2020-12-22 18:27:28 +08:00
|
|
|
#include <filesystem>
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <Shlobj.h>
|
|
|
|
#include <winrt/Windows.Data.Json.h>
|
|
|
|
#include <winrt/Windows.Foundation.Collections.h>
|
|
|
|
|
|
|
|
#include "ZipTools/ZipFolder.h"
|
2020-12-22 22:15:46 +08:00
|
|
|
#include <common/SettingsAPI/settings_helpers.h>
|
|
|
|
#include <common/utils/json.h>
|
|
|
|
#include <common/utils/timeutil.h>
|
2021-01-13 02:48:55 +08:00
|
|
|
#include <common/utils/exec.h>
|
2020-12-22 22:15:46 +08:00
|
|
|
|
|
|
|
#include "ReportMonitorInfo.h"
|
2021-01-22 00:01:28 +08:00
|
|
|
#include "ReportRegistry.h"
|
2020-12-22 18:27:28 +08:00
|
|
|
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" } },
|
2020-12-25 00:05:32 +08:00
|
|
|
{ L"FancyZones\\settings.json", { L"properties/fancyzones_excluded_apps" } }
|
2020-12-22 18:27:28 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
vector<wstring> filesToDelete = {
|
2020-12-25 00:05:32 +08:00
|
|
|
L"PowerToys Run\\Cache",
|
|
|
|
L"PowerRename\\replace-mru.json",
|
2021-01-20 00:43:28 +08:00
|
|
|
L"PowerRename\\search-mru.json",
|
|
|
|
L"PowerToys Run\\Settings\\UserSelectedRecord.json",
|
|
|
|
L"PowerToys Run\\Settings\\QueryHistory.json"
|
2020-12-22 18:27:28 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
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())
|
|
|
|
{
|
2020-12-22 22:15:46 +08:00
|
|
|
hideByXPath(it, xpathArray, p);
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2020-12-22 22:15:46 +08:00
|
|
|
|
2020-12-22 18:27:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (val.ValueType() == JsonValueType::Object)
|
|
|
|
{
|
|
|
|
IJsonValue newVal;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
newVal = val.GetObjectW().GetNamedValue(xpathArray[p]);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2020-12-22 22:15:46 +08:00
|
|
|
|
|
|
|
hideByXPath(newVal, xpathArray, p + 1);
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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())
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
wprintf(L"Failed to parse file %s\n", jsonPath.c_str());
|
2020-12-22 22:15:46 +08:00
|
|
|
return;
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2020-12-24 19:27:49 +08:00
|
|
|
bool deleteFolder(wstring path)
|
2020-12-22 18:27:28 +08:00
|
|
|
{
|
|
|
|
error_code err;
|
|
|
|
remove_all(path, err);
|
|
|
|
if (err.value() != 0)
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
wprintf_s(L"Failed to delete %s. Error code: %d\n", path.c_str(), err.value());
|
2020-12-22 18:27:28 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-12-22 22:15:46 +08:00
|
|
|
void hideUserPrivateInfo(const filesystem::path& dir)
|
2020-12-22 18:27:28 +08:00
|
|
|
{
|
|
|
|
// 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);
|
2020-12-24 19:27:49 +08:00
|
|
|
deleteFolder(path);
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void reportWindowsVersion(const filesystem::path& tmpDir)
|
|
|
|
{
|
|
|
|
auto versionReportPath = tmpDir;
|
|
|
|
versionReportPath = versionReportPath.append("windows-version.txt");
|
|
|
|
OSVERSIONINFOEXW osInfo;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2020-12-22 22:15:46 +08:00
|
|
|
NTSTATUS(WINAPI * RtlGetVersion)
|
|
|
|
(LPOSVERSIONINFOEXW) = nullptr;
|
2020-12-22 18:27:28 +08:00
|
|
|
*(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");
|
2020-12-22 22:15:46 +08:00
|
|
|
if (RtlGetVersion)
|
2020-12-22 18:27:28 +08:00
|
|
|
{
|
|
|
|
osInfo.dwOSVersionInfoSize = sizeof(osInfo);
|
|
|
|
RtlGetVersion(&osInfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to get windows version info\n");
|
2020-12-22 18:27:28 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
wofstream versionReport(versionReportPath);
|
|
|
|
versionReport << "MajorVersion: " << osInfo.dwMajorVersion << endl;
|
|
|
|
versionReport << "MinorVersion: " << osInfo.dwMinorVersion << endl;
|
|
|
|
versionReport << "BuildNumber: " << osInfo.dwBuildNumber << endl;
|
|
|
|
}
|
|
|
|
catch(...)
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to write to %s\n", versionReportPath.string().c_str());
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-13 02:48:55 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-22 18:27:28 +08:00
|
|
|
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
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to retrieve the desktop path. Error code: %d\n", GetLastError());
|
|
|
|
return 1;
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-24 19:27:49 +08:00
|
|
|
auto settingsRootPath = PTSettingsHelper::get_root_save_folder_location();
|
|
|
|
settingsRootPath = settingsRootPath + L"\\";
|
2020-12-22 22:15:46 +08:00
|
|
|
|
2020-12-22 18:27:28 +08:00
|
|
|
// Copy to a temp folder
|
|
|
|
auto tmpDir = temp_directory_path();
|
|
|
|
tmpDir = tmpDir.append("PowerToys\\");
|
2020-12-24 19:27:49 +08:00
|
|
|
if (!deleteFolder(tmpDir))
|
2020-12-22 18:27:28 +08:00
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to delete temp folder\n");
|
2020-12-22 18:27:28 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
copy(settingsRootPath, tmpDir, copy_options::recursive);
|
2020-12-22 22:15:46 +08:00
|
|
|
// Remove updates folder contents
|
2020-12-24 19:27:49 +08:00
|
|
|
deleteFolder(tmpDir / "Updates");
|
2020-12-22 18:27:28 +08:00
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to copy PowerToys folder\n");
|
2020-12-22 18:27:28 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2020-12-22 22:15:46 +08:00
|
|
|
|
|
|
|
// Hide sensitive information
|
2020-12-22 18:27:28 +08:00
|
|
|
hideUserPrivateInfo(tmpDir);
|
|
|
|
|
|
|
|
// Write monitors info to the temporary folder
|
|
|
|
reportMonitorInfo(tmpDir);
|
|
|
|
|
|
|
|
// Write windows version info to the temporary folder
|
|
|
|
reportWindowsVersion(tmpDir);
|
|
|
|
|
2021-01-13 02:48:55 +08:00
|
|
|
// Write dotnet installation info to the temporary folder
|
|
|
|
reportDotNetInstallationInfo(tmpDir);
|
|
|
|
|
2021-01-22 00:01:28 +08:00
|
|
|
// Write registry to the temporary folder
|
|
|
|
reportRegistry(tmpDir);
|
|
|
|
|
2020-12-22 18:27:28 +08:00
|
|
|
// Zip folder
|
|
|
|
auto zipPath = path::path(saveZipPath);
|
2020-12-22 22:15:46 +08:00
|
|
|
std::string reportFilename{"PowerToysReport_"};
|
|
|
|
reportFilename += timeutil::format_as_local("%F-%H-%M-%S", timeutil::now());
|
|
|
|
reportFilename += ".zip";
|
|
|
|
zipPath /= reportFilename;
|
|
|
|
|
2020-12-22 18:27:28 +08:00
|
|
|
try
|
|
|
|
{
|
|
|
|
zipFolder(zipPath, tmpDir);
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
2020-12-24 19:27:49 +08:00
|
|
|
printf("Failed to zip folder\n");
|
2020-12-22 18:27:28 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2020-12-22 22:15:46 +08:00
|
|
|
|
2020-12-24 19:27:49 +08:00
|
|
|
deleteFolder(tmpDir);
|
2020-12-22 18:27:28 +08:00
|
|
|
return 0;
|
2021-01-22 00:01:28 +08:00
|
|
|
}
|