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:
parent
8d74ffbedb
commit
ca8fbe010f
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user