1
0
mirror of https://github.com/valinet/ExplorerPatcher.git synced 2024-12-18 02:16:00 +01:00

When an update is available, the notification displays the version of the update; The updater correctly detects when the current version is a pre-release but the user has switched the update channel to stable and does not suggest the older stable version as an update anymore (multiple reports, #540, #710)

This commit is contained in:
Valentin Radu 2022-01-22 21:12:18 +02:00
parent 8d74ffbedb
commit ca8fbe010f
6 changed files with 183 additions and 19 deletions

View File

@ -27,6 +27,8 @@ Tested on OS build 22000.434.
* Windows 10 * Windows 10
* Simple Window Switcher now highlights windows that require user attention (windows that have their taskbar button flash and colored in orange) (.8) * Simple Window Switcher now highlights windows that require user attention (windows that have their taskbar button flash and colored in orange) (.8)
* Reliability improvements for the option that maps the `Win`+`C` shortcut to open the clock flyout instead of Microsoft Teams (eliminated dependency on symbol data) (.10) * Reliability improvements for the option that maps the `Win`+`C` shortcut to open the clock flyout instead of Microsoft Teams (eliminated dependency on symbol data) (.10)
* When an update is available, the notification displays the version of the update (.12)
* The updater correctly detects when the current version is a pre-release but the user has switched the update channel to stable and does not suggest the older stable version as an update anymore (multiple reports, #540, #710) (.12)
#### Fixes #### Fixes

View File

@ -64,7 +64,9 @@ BOOL IsUpdateAvailableHelper(
__x_ABI_CWindows_CUI_CNotifications_CIToastNotification** toast, __x_ABI_CWindows_CUI_CNotifications_CIToastNotification** toast,
BOOL bUpdatePreferStaging, BOOL bUpdatePreferStaging,
WCHAR* wszInfoURL, WCHAR* wszInfoURL,
DWORD dwInfoURLLen DWORD dwInfoURLLen,
HMODULE hModule,
DWORD* pLeftMost, DWORD* pSecondLeft, DWORD* pSecondRight, DWORD* pRightMost
) )
{ {
BOOL bIsUpdateAvailable = FALSE; BOOL bIsUpdateAvailable = FALSE;
@ -199,15 +201,127 @@ BOOL IsUpdateAvailableHelper(
#ifdef UPDATES_VERBOSE_OUTPUT #ifdef UPDATES_VERBOSE_OUTPUT
printf("[Updates] Hash of remote file is \"%s\" (%s).\n", DOSMODE_OFFSET + hash, (hash[0] == 0x4D && hash[1] == 0x5A) ? "valid" : "invalid"); printf("[Updates] Hash of remote file is \"%s\" (%s).\n", DOSMODE_OFFSET + hash, (hash[0] == 0x4D && hash[1] == 0x5A) ? "valid" : "invalid");
#endif #endif
if (hash[0] == 0x4D && hash[1] == 0x5A && _stricmp(DOSMODE_OFFSET + hash, szCheckAgainst)) BOOL bOldType = TRUE;
char *szLeftMost = NULL, *szSecondLeft = NULL, *szSecondRight = NULL, *szRightMost = NULL, *szRealHash = NULL;
if (hModule)
{ {
bIsUpdateAvailable = TRUE; if (hash[0] == 0x4D && hash[1] == 0x5A)
{
if (strchr(DOSMODE_OFFSET + hash, '.'))
{
szLeftMost = DOSMODE_OFFSET + hash;
if (szSecondLeft = strchr(szLeftMost, '.'))
{
*szSecondLeft = 0;
szSecondLeft++;
if (szSecondRight = strchr(szSecondLeft, '.'))
{
*szSecondRight = 0;
szSecondRight++;
if (szRightMost = strchr(szSecondRight, '.'))
{
*szRightMost = 0;
szRightMost++;
if (szRealHash = strchr(szRightMost, '.'))
{
bOldType = FALSE;
*szRealHash = 0;
szRealHash++;
DWORD dwRemoteLeftMost = atoi(szLeftMost);
if (pLeftMost) *pLeftMost = dwRemoteLeftMost;
DWORD dwRemoteSecondLeft = atoi(szSecondLeft);
if (pSecondLeft) *pSecondLeft = dwRemoteSecondLeft;
DWORD dwRemoteSecondRight = atoi(szSecondRight);
if (pSecondRight) *pSecondRight = dwRemoteSecondRight;
DWORD dwRemoteRightMost = atoi(szRightMost);
if (pRightMost) *pRightMost = dwRemoteRightMost;
DWORD dwLocalLeftMost = 0;
DWORD dwLocalSecondLeft = 0;
DWORD dwLocalSecondRight = 0;
DWORD dwLocalRightMost = 0;
QueryVersionInfo(hModule, VS_VERSION_INFO, &dwLocalLeftMost, &dwLocalSecondLeft, &dwLocalSecondRight, &dwLocalRightMost);
int res = 0;
if (!res)
{
if (dwLocalLeftMost < dwRemoteLeftMost)
{
res = -1;
}
if (dwLocalLeftMost > dwRemoteLeftMost)
{
res = 1;
}
if (!res)
{
if (dwLocalSecondLeft < dwRemoteSecondLeft)
{
res = -1;
}
if (dwLocalSecondLeft > dwRemoteSecondLeft)
{
res = 1;
}
if (!res)
{
if (dwLocalSecondRight < dwRemoteSecondRight)
{
res = -1;
}
if (dwLocalSecondRight > dwRemoteSecondRight)
{
res = 1;
}
if (!res)
{
if (dwLocalRightMost < dwRemoteRightMost)
{
res = -1;
}
if (dwLocalRightMost > dwRemoteRightMost)
{
res = 1;
}
}
}
}
}
if (res == -1)
{
bIsUpdateAvailable = TRUE;
}
else if (res == 0)
{
*(szSecondLeft - 1) = '.';
*(szSecondRight - 1) = '.';
*(szRightMost - 1) = '.';
*(szRealHash - 1) = '.';
if (_stricmp(DOSMODE_OFFSET + hash, szCheckAgainst))
{
bIsUpdateAvailable = TRUE;
}
}
}
}
}
}
}
}
}
if (bOldType)
{
if (hash[0] == 0x4D && hash[1] == 0x5A && _stricmp(DOSMODE_OFFSET + hash, szCheckAgainst))
{
bIsUpdateAvailable = TRUE;
}
} }
} }
else else
{ {
#ifdef UPDATES_VERBOSE_OUTPUT #ifdef UPDATES_VERBOSE_OUTPUT
printf("[Updates] Failed. Read %d bytes.\n"); printf("[Updates] Failed. Read %d bytes.\n", dwRead);
#endif #endif
if (lpFail) *lpFail = TRUE; if (lpFail) *lpFail = TRUE;
} }
@ -439,7 +553,9 @@ BOOL IsUpdateAvailableHelper(
return bIsUpdateAvailable; return bIsUpdateAvailable;
} }
BOOL IsUpdateAvailable(LPCWSTR wszDataStore, char* szCheckAgainst, BOOL* lpFail, WCHAR* wszInfoURL, DWORD dwInfoURLLen) BOOL IsUpdateAvailable(LPCWSTR wszDataStore, char* szCheckAgainst, BOOL* lpFail, WCHAR* wszInfoURL, DWORD dwInfoURLLen, HMODULE hModule,
DWORD* pLeftMost, DWORD* pSecondLeft, DWORD* pSecondRight, DWORD* pRightMost
)
{ {
HKEY hKey = NULL; HKEY hKey = NULL;
DWORD dwSize = 0; DWORD dwSize = 0;
@ -539,7 +655,9 @@ BOOL IsUpdateAvailable(LPCWSTR wszDataStore, char* szCheckAgainst, BOOL* lpFail,
NULL, NULL, NULL, NULL, NULL, NULL,
bUpdatePreferStaging, bUpdatePreferStaging,
wszInfoURL, wszInfoURL,
dwInfoURLLen dwInfoURLLen,
hModule,
pLeftMost, pSecondLeft, pSecondRight, pRightMost
); );
} }
@ -547,7 +665,8 @@ BOOL UpdateProduct(
LPCWSTR wszDataStore, LPCWSTR wszDataStore,
__x_ABI_CWindows_CUI_CNotifications_CIToastNotifier* notifier, __x_ABI_CWindows_CUI_CNotifications_CIToastNotifier* notifier,
__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationFactory* notifFactory, __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationFactory* notifFactory,
__x_ABI_CWindows_CUI_CNotifications_CIToastNotification** toast __x_ABI_CWindows_CUI_CNotifications_CIToastNotification** toast,
HMODULE hModule
) )
{ {
HKEY hKey = NULL; HKEY hKey = NULL;
@ -635,7 +754,9 @@ BOOL UpdateProduct(
notifFactory, notifFactory,
toast, toast,
bUpdatePreferStaging, bUpdatePreferStaging,
NULL, 0 NULL, 0,
hModule,
NULL, NULL, NULL, NULL
); );
} }
@ -819,16 +940,17 @@ BOOL InstallUpdatesIfAvailable(
CHAR hash[100]; CHAR hash[100];
ZeroMemory(hash, 100 * sizeof(CHAR)); ZeroMemory(hash, 100 * sizeof(CHAR));
ComputeFileHash(dllName, hash, 100); ComputeFileHash2(hModule, dllName, hash, 100);
BOOL bFail = FALSE; BOOL bFail = FALSE;
if (IsUpdateAvailable(_T(REGPATH), hash, &bFail, wszInfoURL, MAX_PATH)) dwLeftMost = 0; dwSecondLeft = 0; dwSecondRight = 0; dwRightMost = 0;
if (IsUpdateAvailable(_T(REGPATH), hash, &bFail, wszInfoURL, MAX_PATH, hModule, &dwLeftMost, &dwSecondLeft, &dwSecondRight, &dwRightMost))
{ {
printf("[Updates] An update is available.\n"); printf("[Updates] An update is available.\n");
if ((dwOperation == UPDATES_OP_DEFAULT && dwUpdatePolicy == UPDATE_POLICY_AUTO) || (dwOperation == UPDATES_OP_INSTALL)) if ((dwOperation == UPDATES_OP_DEFAULT && dwUpdatePolicy == UPDATE_POLICY_AUTO) || (dwOperation == UPDATES_OP_INSTALL))
{ {
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
BOOL bOk = UpdateProduct(_T(REGPATH), notifier, notifFactory, toast); BOOL bOk = UpdateProduct(_T(REGPATH), notifier, notifFactory, toast, hModule);
if (!bOk) if (!bOk)
{ {
if (dwOperation == UPDATES_OP_INSTALL) if (dwOperation == UPDATES_OP_INSTALL)
@ -885,14 +1007,23 @@ BOOL InstallUpdatesIfAvailable(
L"activationType=\"protocol\" launch=\"%s\" duration=\"long\">\r\n" L"activationType=\"protocol\" launch=\"%s\" duration=\"long\">\r\n"
L" <visual>\r\n" L" <visual>\r\n"
L" <binding template=\"ToastGeneric\">\r\n" L" <binding template=\"ToastGeneric\">\r\n"
L" <text><![CDATA[New version available]]></text>\r\n" L" <text><![CDATA[%s available]]></text>\r\n"
L" <text><![CDATA[You can update by right clicking the taskbar, choosing \"Properties\", then \"Updates\". Click here to learn more about this update.]]></text>\r\n" L" <text><![CDATA[You can update by right clicking the taskbar, choosing \"Properties\", then \"Updates\". Click here to learn more about this update.]]></text>\r\n"
L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n" L" <text placement=\"attribution\"><![CDATA[ExplorerPatcher]]></text>\r\n"
L" </binding>\r\n" L" </binding>\r\n"
L" </visual>\r\n" L" </visual>\r\n"
L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n" L" <audio src=\"ms-winsoundevent:Notification.Default\" loop=\"false\" silent=\"false\"/>\r\n"
L"</toast>\r\n"; L"</toast>\r\n";
swprintf_s(buf, TOAST_BUFSIZ, text, wszInfoURL); if (!dwLeftMost)
{
swprintf_s(buf, TOAST_BUFSIZ, text, wszInfoURL, L"New version");
}
else
{
WCHAR wszVersionInfo[100];
swprintf_s(wszVersionInfo, 100, L"Version %d.%d.%d.%d is", dwLeftMost, dwSecondLeft, dwSecondRight, dwRightMost);
swprintf_s(buf, TOAST_BUFSIZ, text, wszInfoURL, wszVersionInfo);
}
__x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL; __x_ABI_CWindows_CData_CXml_CDom_CIXmlDocument* inputXml = NULL;
String2IXMLDocument( String2IXMLDocument(
buf, buf,

View File

@ -297,7 +297,7 @@ void* ReadFromFile(wchar_t* wszFileName, DWORD* dwSize)
return ok; return ok;
} }
int ComputeFileHash(LPCWSTR filename, LPCSTR hash, DWORD dwHash) int ComputeFileHash(LPCWSTR filename, LPSTR hash, DWORD dwHash)
{ {
DWORD dwStatus = 0; DWORD dwStatus = 0;
BOOL bResult = FALSE; BOOL bResult = FALSE;
@ -409,6 +409,33 @@ int ComputeFileHash(LPCWSTR filename, LPCSTR hash, DWORD dwHash)
return dwStatus; return dwStatus;
} }
int ComputeFileHash2(HMODULE hModule, LPCWSTR filename, LPSTR hash, DWORD dwHash)
{
if (dwHash < 33)
{
return ERROR_BUFFER_OVERFLOW;
}
if (!hModule)
{
return ERROR_INVALID_ADDRESS;
}
DWORD dwLeftMost = 0;
DWORD dwSecondLeft = 0;
DWORD dwSecondRight = 0;
DWORD dwRightMost = 0;
QueryVersionInfo(hModule, VS_VERSION_INFO, &dwLeftMost, &dwSecondLeft, &dwSecondRight, &dwRightMost);
sprintf_s(hash, 33, "%d.%d.%d.%d.", dwLeftMost, dwSecondLeft, dwSecondRight, dwRightMost);
char real_hash[33];
ComputeFileHash(filename, real_hash, 33);
strncpy_s(hash + strlen(hash), dwHash, real_hash, 32 - strlen(hash));
hash[33] = 0;
return ERROR_SUCCESS;
}
void LaunchPropertiesGUI(HMODULE hModule) void LaunchPropertiesGUI(HMODULE hModule)
{ {
//CreateThread(0, 0, ZZGUI, 0, 0, 0); //CreateThread(0, 0, ZZGUI, 0, 0, 0);

View File

@ -241,7 +241,9 @@ static BOOL AppsShouldUseDarkMode() { return TRUE; }
void* ReadFromFile(wchar_t* wszFileName, DWORD* dwSize); void* ReadFromFile(wchar_t* wszFileName, DWORD* dwSize);
int ComputeFileHash(LPCWSTR filename, LPCSTR hash, DWORD dwHash); int ComputeFileHash(LPCWSTR filename, LPSTR hash, DWORD dwHash);
int ComputeFileHash2(HMODULE hModule, LPCWSTR filename, LPSTR hash, DWORD dwHash);
void LaunchPropertiesGUI(HMODULE hModule); void LaunchPropertiesGUI(HMODULE hModule);

View File

@ -14,10 +14,12 @@ int WINAPI wWinMain(
GetModuleFileNameW(GetModuleHandle(NULL), wszPath, MAX_PATH); GetModuleFileNameW(GetModuleHandle(NULL), wszPath, MAX_PATH);
PathRemoveFileSpecW(wszPath); PathRemoveFileSpecW(wszPath);
wcscat_s(wszPath, MAX_PATH, L"\\" _T(PRODUCT_NAME) L".amd64.dll"); wcscat_s(wszPath, MAX_PATH, L"\\" _T(PRODUCT_NAME) L".amd64.dll");
HMODULE hModule = LoadLibraryExW(wszPath, NULL, LOAD_LIBRARY_AS_DATAFILE);
CHAR hash[100]; CHAR hash[100];
ZeroMemory(hash, 100); ZeroMemory(hash, 100);
ComputeFileHash(wszPath, hash, 100); ComputeFileHash2(hModule, wszPath, hash, 100);
FreeLibrary(hModule);
PathRemoveFileSpecW(wszPath); PathRemoveFileSpecW(wszPath);
wcscat_s(wszPath, MAX_PATH, L"\\" _T(SETUP_UTILITY_NAME)); wcscat_s(wszPath, MAX_PATH, L"\\" _T(SETUP_UTILITY_NAME));

View File

@ -1,7 +1,7 @@
#define VER_MAJOR 22000 #define VER_MAJOR 22000
#define VER_MINOR 434 #define VER_MINOR 434
#define VER_BUILD_HI 41 #define VER_BUILD_HI 41
#define VER_BUILD_LO 11 #define VER_BUILD_LO 12
#define VER_FLAGS VS_FF_PRERELEASE #define VER_FLAGS VS_FF_PRERELEASE
@ -12,5 +12,5 @@
#define VER_STR(arg) #arg #define VER_STR(arg) #arg
// The String form of the version numbers // The String form of the version numbers
#define VER_FILE_STRING VALUE "FileVersion", "22000.434.41.11" #define VER_FILE_STRING VALUE "FileVersion", "22000.434.41.12"
#define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.434.41.11" #define VER_PRODUCT_STRING VALUE "ProductVersion", "22000.434.41.12"