Set INSTALLLOCATION in one single place

It used to be set both in AppSearch action (using RegLocator table),
and in MigrateInstallPath custom action. This would overwrite value
of INSTALLLOCATION taken from user, and read on the previous step,
with values taken on the next step.

Only migrating the install location in one single place - in custom
action MigrateInstallPath - makes the process controllable. Also it
allows to easily see all the various places in registry we read.

Change-Id: Ib7e04c26e71ba92c6a62a0511971bfb3bdb7db72
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87867
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
This commit is contained in:
Mike Kaganski 2020-02-03 14:48:21 +03:00
parent b5bec747cc
commit 61e2314698
3 changed files with 42 additions and 44 deletions

View file

@ -1,9 +1,5 @@
Property Signature_ Property Signature_
s72 s72 s72 s72
AppSearch Property Signature_ AppSearch Property Signature_
INSTALLLOCATION installuser
INSTALLLOCATION installuser_
INSTALLLOCATION installmachine
INSTALLLOCATION installmachine_
WIN81S14 win81s14 WIN81S14 win81s14
WINMAJORVER WinMajorVer WINMAJORVER WinMajorVer

View file

@ -1,8 +1,4 @@
Signature_ Root Key Name Type Signature_ Root Key Name Type
s72 i2 s255 S255 I2 s72 i2 s255 S255 I2
RegLocator Signature_ RegLocator Signature_
installuser 1 Software\LibreOffice\Layers\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
installuser_ 1 Software\LibreOffice\Layers_\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
installmachine 2 Software\LibreOffice\Layers\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
installmachine_ 2 Software\LibreOffice\Layers_\[DEFINEDPRODUCT]\[BRANDPACKAGEVERSION] INSTALLLOCATION 2
WinMajorVer 2 Software\Microsoft\Windows NT\CurrentVersion CurrentMajorVersionNumber 2 WinMajorVer 2 Software\Microsoft\Windows NT\CurrentVersion CurrentMajorVersionNumber 2

View file

@ -24,65 +24,71 @@
extern "C" __declspec(dllexport) UINT __stdcall MigrateInstallPath(MSIHANDLE handle) extern "C" __declspec(dllexport) UINT __stdcall MigrateInstallPath(MSIHANDLE handle)
{ {
std::wstring sInstDir = GetMsiPropertyW(handle, L"INSTALLLOCATION");
if (!sInstDir.empty())
return ERROR_SUCCESS; // Don't overwrite explicitly set value
auto RegValue = [](HKEY hRoot, const WCHAR* sKey, const WCHAR* sVal) { auto RegValue = [](HKEY hRoot, const WCHAR* sKey, const WCHAR* sVal) {
std::wstring sResult; std::wstring sResult;
WCHAR buf[32767]; // max longpath
if (HKEY hKey; RegOpenKeyW(hRoot, sKey, &hKey) == ERROR_SUCCESS) DWORD bufsize = sizeof(buf); // yes, it is the number of bytes
{ if (RegGetValueW(hRoot, sKey, sVal, RRF_RT_REG_SZ, nullptr, buf, &bufsize) == ERROR_SUCCESS)
WCHAR buf[32767]; // max longpath sResult = buf; // RegGetValueW null-terminates strings
DWORD bufsize = sizeof(buf); // yes, it is the number of bytes
if (RegQueryValueExW(hKey, sVal, nullptr, nullptr, reinterpret_cast<LPBYTE>(buf),
&bufsize)
== ERROR_SUCCESS)
{
buf[std::min<size_t>(SAL_N_ELEMENTS(buf) - 1, bufsize / sizeof(*buf))] = 0;
sResult = buf;
}
RegCloseKey(hKey);
}
return sResult; return sResult;
}; };
std::wstring sManufacturer = GetMsiPropertyW( handle, L"Manufacturer" ); const std::wstring sManufacturer = GetMsiPropertyW( handle, L"Manufacturer" );
std::wstring sDefinedName = GetMsiPropertyW( handle, L"DEFINEDPRODUCT" ); const std::wstring sDefinedName = GetMsiPropertyW( handle, L"DEFINEDPRODUCT" );
std::wstring sUpdateVersion = GetMsiPropertyW( handle, L"DEFINEDVERSION" ); const std::wstring sUpdateVersion = GetMsiPropertyW( handle, L"DEFINEDVERSION" );
std::wstring sUpgradeCode = GetMsiPropertyW( handle, L"UpgradeCode" ); const std::wstring sUpgradeCode = GetMsiPropertyW( handle, L"UpgradeCode" );
const std::wstring sBrandPackageVersion = GetMsiPropertyW(handle, L"BRANDPACKAGEVERSION");
std::wstring sKey = L"Software\\" + sManufacturer + L"\\" + sDefinedName + std::wstring sKey = L"Software\\" + sManufacturer + L"\\" + sDefinedName +
L"\\" + sUpdateVersion + L"\\" + sUpgradeCode; L"\\" + sUpdateVersion + L"\\" + sUpgradeCode;
if (auto sInstDir = RegValue(HKEY_CURRENT_USER, sKey.c_str(), L"INSTALLLOCATION"); sInstDir = RegValue(HKEY_CURRENT_USER, sKey.c_str(), L"INSTALLLOCATION");
!sInstDir.empty()) if (sInstDir.empty())
sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"INSTALLLOCATION");
// See #i93032# for layers description
if (sInstDir.empty())
{ {
MsiSetPropertyW(handle, L"INSTALLLOCATION", sInstDir.c_str()); sKey = L"Software\\LibreOffice\\Layers\\" + sDefinedName + L"\\" + sBrandPackageVersion;
// MessageBoxW( NULL, sInstDir.c_str(), L"Found in HKEY_CURRENT_USER", MB_OK ); sInstDir = RegValue(HKEY_CURRENT_USER, sKey.c_str(), L"INSTALLLOCATION");
} }
else if (auto sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"INSTALLLOCATION"); if (sInstDir.empty())
!sInstDir.empty())
{ {
MsiSetPropertyW(handle, L"INSTALLLOCATION", sInstDir.c_str()); sKey = L"Software\\LibreOffice\\Layers_\\" + sDefinedName + L"\\" + sBrandPackageVersion;
// MessageBoxW( NULL, sInstDir.c_str(), L"Found in HKEY_LOCAL_MACHINE", MB_OK ); sInstDir = RegValue(HKEY_CURRENT_USER, sKey.c_str(), L"INSTALLLOCATION");
} }
else if (std::wistringstream sOlds{ GetMsiPropertyW(handle, L"OLDPRODUCTS") }; !sOlds.eof()) if (sInstDir.empty())
{ {
sKey = L"Software\\LibreOffice\\Layers\\" + sDefinedName + L"\\" + sBrandPackageVersion;
sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"INSTALLLOCATION");
}
if (sInstDir.empty())
{
sKey = L"Software\\LibreOffice\\Layers_\\" + sDefinedName + L"\\" + sBrandPackageVersion;
sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"INSTALLLOCATION");
}
if (sInstDir.empty())
{
std::wistringstream sOlds{ GetMsiPropertyW(handle, L"OLDPRODUCTS") };
std::wstring sOld; std::wstring sOld;
bool bFound = false; while (std::getline(sOlds, sOld, L';'))
while (!bFound && std::getline(sOlds, sOld, L';'))
{ {
if (sOld.empty()) if (sOld.empty())
continue; continue;
sKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + sOld; sKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + sOld;
if (auto sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"InstallLocation"); sInstDir = RegValue(HKEY_LOCAL_MACHINE, sKey.c_str(), L"InstallLocation");
!sInstDir.empty()) if (!sInstDir.empty())
{ break;
MsiSetPropertyW(handle, L"INSTALLLOCATION", sInstDir.c_str());
// MessageBoxW( NULL, sInstDir.c_str(), L"Found in Uninstall", MB_OK );
bFound = true;
}
} }
} }
if (!sInstDir.empty())
MsiSetPropertyW(handle, L"INSTALLLOCATION", sInstDir.c_str());
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }