[Bug Report Tool] Report installation folder structure (#12425)

* Report installation folder structure

* Hanlde case when GetModuleFileName fails

* spelling

* PR comments
This commit is contained in:
Mykhailo Pylyp 2021-07-20 10:33:00 +03:00 committed by GitHub
parent e6ffbcf315
commit 91797669ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 236 additions and 1 deletions

View File

@ -192,6 +192,7 @@ buildtools
buildtransitive
BValue
bytearray
CALG
callbackptr
Camer
Cangjie
@ -707,6 +708,7 @@ Hardlines
HARDWAREINPUT
hashcode
Hashset
HASHVAL
hbitmap
hbmp
hbr
@ -714,6 +716,8 @@ HBRBACKGROUND
HBRUSH
hcblack
HCERTSTORE
HCRYPTHASH
HCRYPTPROV
hcwhite
hdc
HDF
@ -2214,6 +2218,7 @@ VDId
vec
VERBSONLY
VERBW
VERIFYCONTEXT
verrsrc
VERSIONINFO
Versioning

View File

@ -30,7 +30,7 @@
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>Wevtapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<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>
@ -38,6 +38,7 @@
<WarningLevel>TurnOffAllWarnings</WarningLevel>
</ClCompile>
<ClCompile Include="EventViewer.cpp" />
<ClCompile Include="InstallationFolder.cpp" />
<ClCompile Include="ReportMonitorInfo.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="RegistryUtils.cpp" />
@ -56,6 +57,7 @@
<ClInclude Include="..\..\..\deps\cziplib\src\miniz.h" />
<ClInclude Include="..\..\..\deps\cziplib\src\zip.h" />
<ClInclude Include="EventViewer.h" />
<ClInclude Include="InstallationFolder.h" />
<ClInclude Include="ReportMonitorInfo.h" />
<ClInclude Include="..\..\..\common\utils\json.h" />
<ClInclude Include="RegistryUtils.h" />

View File

@ -13,6 +13,7 @@
<ClCompile Include="RegistryUtils.cpp" />
<ClCompile Include="EventViewer.cpp" />
<ClCompile Include="XmlDocumentEx.cpp" />
<ClCompile Include="InstallationFolder.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="ZipTools">
@ -30,5 +31,6 @@
<ClInclude Include="RegistryUtils.h" />
<ClInclude Include="EventViewer.h" />
<ClInclude Include="XmlDocumentEx.h" />
<ClInclude Include="InstallationFolder.h" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,216 @@
#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 = (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)
{
DWORD dwStatus = 0;
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());
}
while (bResult = ReadFile(hFile, rgbFile, bufferSize, &cbRead, NULL))
{
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());;
}
}
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
{
std::wstring 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 os = std::wofstream(path);
return os;
}
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());
}
}

View File

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

View File

@ -17,6 +17,7 @@
#include "ReportMonitorInfo.h"
#include "RegistryUtils.h"
#include "EventViewer.h"
#include "InstallationFolder.h"
using namespace std;
using namespace std::filesystem;
@ -298,6 +299,8 @@ int wmain(int argc, wchar_t* argv[], wchar_t*)
return 1;
}
InstallationFolder::ReportStructure(reportDir);
// Hide sensitive information
HideUserPrivateInfo(reportDir);